diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2008-10-17 12:20:26 -0400 |
---|---|---|
committer | Arjan van de Ven <arjan@linux.intel.com> | 2008-10-17 12:20:26 -0400 |
commit | 651dab4264e4ba0e563f5ff56f748127246e9065 (patch) | |
tree | 016630974bdcb00fe529b673f96d389e0fd6dc94 /net/mac80211 | |
parent | 40b8606253552109815786e5d4b0de98782d31f5 (diff) | |
parent | 2e532d68a2b3e2aa6b19731501222069735c741c (diff) |
Merge commit 'linus/master' into merge-linus
Conflicts:
arch/x86/kvm/i8254.c
Diffstat (limited to 'net/mac80211')
39 files changed, 6657 insertions, 5309 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 80d693392b0f..7f710a27e91c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -22,6 +22,11 @@ config MAC80211_RC_PID | |||
22 | mac80211 that uses a PID controller to select the TX | 22 | mac80211 that uses a PID controller to select the TX |
23 | rate. | 23 | rate. |
24 | 24 | ||
25 | config MAC80211_RC_MINSTREL | ||
26 | bool "Minstrel" | ||
27 | ---help--- | ||
28 | This option enables the 'minstrel' TX rate control algorithm | ||
29 | |||
25 | choice | 30 | choice |
26 | prompt "Default rate control algorithm" | 31 | prompt "Default rate control algorithm" |
27 | default MAC80211_RC_DEFAULT_PID | 32 | default MAC80211_RC_DEFAULT_PID |
@@ -39,11 +44,19 @@ config MAC80211_RC_DEFAULT_PID | |||
39 | default rate control algorithm. You should choose | 44 | default rate control algorithm. You should choose |
40 | this unless you know what you are doing. | 45 | this unless you know what you are doing. |
41 | 46 | ||
47 | config MAC80211_RC_DEFAULT_MINSTREL | ||
48 | bool "Minstrel" | ||
49 | depends on MAC80211_RC_MINSTREL | ||
50 | ---help--- | ||
51 | Select Minstrel as the default rate control algorithm. | ||
52 | |||
53 | |||
42 | endchoice | 54 | endchoice |
43 | 55 | ||
44 | config MAC80211_RC_DEFAULT | 56 | config MAC80211_RC_DEFAULT |
45 | string | 57 | string |
46 | default "pid" if MAC80211_RC_DEFAULT_PID | 58 | default "pid" if MAC80211_RC_DEFAULT_PID |
59 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL | ||
47 | default "" | 60 | default "" |
48 | 61 | ||
49 | endmenu | 62 | endmenu |
@@ -179,19 +192,6 @@ config MAC80211_VERBOSE_MPL_DEBUG | |||
179 | 192 | ||
180 | Do not select this option. | 193 | Do not select this option. |
181 | 194 | ||
182 | config MAC80211_LOWTX_FRAME_DUMP | ||
183 | bool "Debug frame dumping" | ||
184 | depends on MAC80211_DEBUG_MENU | ||
185 | ---help--- | ||
186 | Selecting this option will cause the stack to | ||
187 | print a message for each frame that is handed | ||
188 | to the lowlevel driver for transmission. This | ||
189 | message includes all MAC addresses and the | ||
190 | frame control field. | ||
191 | |||
192 | If unsure, say N and insert the debugging code | ||
193 | you require into the driver you are debugging. | ||
194 | |||
195 | config MAC80211_DEBUG_COUNTERS | 195 | config MAC80211_DEBUG_COUNTERS |
196 | bool "Extra statistics for TX/RX debugging" | 196 | bool "Extra statistics for TX/RX debugging" |
197 | depends on MAC80211_DEBUG_MENU | 197 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index a169b0201d61..31cfd1f89a72 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -7,6 +7,8 @@ mac80211-y := \ | |||
7 | sta_info.o \ | 7 | sta_info.o \ |
8 | wep.o \ | 8 | wep.o \ |
9 | wpa.o \ | 9 | wpa.o \ |
10 | scan.o \ | ||
11 | ht.o \ | ||
10 | mlme.o \ | 12 | mlme.o \ |
11 | iface.o \ | 13 | iface.o \ |
12 | rate.o \ | 14 | rate.o \ |
@@ -15,6 +17,7 @@ mac80211-y := \ | |||
15 | aes_ccm.o \ | 17 | aes_ccm.o \ |
16 | cfg.o \ | 18 | cfg.o \ |
17 | rx.o \ | 19 | rx.o \ |
20 | spectmgmt.o \ | ||
18 | tx.o \ | 21 | tx.o \ |
19 | key.o \ | 22 | key.o \ |
20 | util.o \ | 23 | util.o \ |
@@ -38,4 +41,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
38 | rc80211_pid-y := rc80211_pid_algo.o | 41 | rc80211_pid-y := rc80211_pid_algo.o |
39 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | 42 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o |
40 | 43 | ||
44 | rc80211_minstrel-y := rc80211_minstrel.o | ||
45 | rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o | ||
46 | |||
41 | mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) | 47 | mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) |
48 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 297c257864c7..855126a3039d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -17,26 +17,26 @@ | |||
17 | #include "rate.h" | 17 | #include "rate.h" |
18 | #include "mesh.h" | 18 | #include "mesh.h" |
19 | 19 | ||
20 | static enum ieee80211_if_types | 20 | struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy) |
21 | nl80211_type_to_mac80211_type(enum nl80211_iftype type) | 21 | { |
22 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
23 | return &local->hw; | ||
24 | } | ||
25 | EXPORT_SYMBOL(wiphy_to_hw); | ||
26 | |||
27 | static bool nl80211_type_check(enum nl80211_iftype type) | ||
22 | { | 28 | { |
23 | switch (type) { | 29 | switch (type) { |
24 | case NL80211_IFTYPE_UNSPECIFIED: | ||
25 | return IEEE80211_IF_TYPE_STA; | ||
26 | case NL80211_IFTYPE_ADHOC: | 30 | case NL80211_IFTYPE_ADHOC: |
27 | return IEEE80211_IF_TYPE_IBSS; | ||
28 | case NL80211_IFTYPE_STATION: | 31 | case NL80211_IFTYPE_STATION: |
29 | return IEEE80211_IF_TYPE_STA; | ||
30 | case NL80211_IFTYPE_MONITOR: | 32 | case NL80211_IFTYPE_MONITOR: |
31 | return IEEE80211_IF_TYPE_MNTR; | ||
32 | #ifdef CONFIG_MAC80211_MESH | 33 | #ifdef CONFIG_MAC80211_MESH |
33 | case NL80211_IFTYPE_MESH_POINT: | 34 | case NL80211_IFTYPE_MESH_POINT: |
34 | return IEEE80211_IF_TYPE_MESH_POINT; | ||
35 | #endif | 35 | #endif |
36 | case NL80211_IFTYPE_WDS: | 36 | case NL80211_IFTYPE_WDS: |
37 | return IEEE80211_IF_TYPE_WDS; | 37 | return true; |
38 | default: | 38 | default: |
39 | return IEEE80211_IF_TYPE_INVALID; | 39 | return false; |
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
@@ -45,17 +45,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
45 | struct vif_params *params) | 45 | struct vif_params *params) |
46 | { | 46 | { |
47 | struct ieee80211_local *local = wiphy_priv(wiphy); | 47 | struct ieee80211_local *local = wiphy_priv(wiphy); |
48 | enum ieee80211_if_types itype; | ||
49 | struct net_device *dev; | 48 | struct net_device *dev; |
50 | struct ieee80211_sub_if_data *sdata; | 49 | struct ieee80211_sub_if_data *sdata; |
51 | int err; | 50 | int err; |
52 | 51 | ||
53 | itype = nl80211_type_to_mac80211_type(type); | 52 | if (!nl80211_type_check(type)) |
54 | if (itype == IEEE80211_IF_TYPE_INVALID) | ||
55 | return -EINVAL; | 53 | return -EINVAL; |
56 | 54 | ||
57 | err = ieee80211_if_add(local, name, &dev, itype, params); | 55 | err = ieee80211_if_add(local, name, &dev, type, params); |
58 | if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) | 56 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) |
59 | return err; | 57 | return err; |
60 | 58 | ||
61 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 59 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -66,13 +64,16 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
66 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 64 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) |
67 | { | 65 | { |
68 | struct net_device *dev; | 66 | struct net_device *dev; |
67 | struct ieee80211_sub_if_data *sdata; | ||
69 | 68 | ||
70 | /* we're under RTNL */ | 69 | /* we're under RTNL */ |
71 | dev = __dev_get_by_index(&init_net, ifindex); | 70 | dev = __dev_get_by_index(&init_net, ifindex); |
72 | if (!dev) | 71 | if (!dev) |
73 | return -ENODEV; | 72 | return -ENODEV; |
74 | 73 | ||
75 | ieee80211_if_remove(dev); | 74 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
75 | |||
76 | ieee80211_if_remove(sdata); | ||
76 | 77 | ||
77 | return 0; | 78 | return 0; |
78 | } | 79 | } |
@@ -81,9 +82,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
81 | enum nl80211_iftype type, u32 *flags, | 82 | enum nl80211_iftype type, u32 *flags, |
82 | struct vif_params *params) | 83 | struct vif_params *params) |
83 | { | 84 | { |
84 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
85 | struct net_device *dev; | 85 | struct net_device *dev; |
86 | enum ieee80211_if_types itype; | ||
87 | struct ieee80211_sub_if_data *sdata; | 86 | struct ieee80211_sub_if_data *sdata; |
88 | int ret; | 87 | int ret; |
89 | 88 | ||
@@ -92,25 +91,24 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
92 | if (!dev) | 91 | if (!dev) |
93 | return -ENODEV; | 92 | return -ENODEV; |
94 | 93 | ||
95 | itype = nl80211_type_to_mac80211_type(type); | 94 | if (!nl80211_type_check(type)) |
96 | if (itype == IEEE80211_IF_TYPE_INVALID) | ||
97 | return -EINVAL; | 95 | return -EINVAL; |
98 | 96 | ||
99 | if (dev == local->mdev) | ||
100 | return -EOPNOTSUPP; | ||
101 | |||
102 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 97 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
103 | 98 | ||
104 | ret = ieee80211_if_change_type(sdata, itype); | 99 | ret = ieee80211_if_change_type(sdata, type); |
105 | if (ret) | 100 | if (ret) |
106 | return ret; | 101 | return ret; |
107 | 102 | ||
103 | if (netif_running(sdata->dev)) | ||
104 | return -EBUSY; | ||
105 | |||
108 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 106 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
109 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 107 | ieee80211_sdata_set_mesh_id(sdata, |
110 | params->mesh_id_len, | 108 | params->mesh_id_len, |
111 | params->mesh_id); | 109 | params->mesh_id); |
112 | 110 | ||
113 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) | 111 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) |
114 | return 0; | 112 | return 0; |
115 | 113 | ||
116 | sdata->u.mntr_flags = *flags; | 114 | sdata->u.mntr_flags = *flags; |
@@ -121,16 +119,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
121 | u8 key_idx, u8 *mac_addr, | 119 | u8 key_idx, u8 *mac_addr, |
122 | struct key_params *params) | 120 | struct key_params *params) |
123 | { | 121 | { |
124 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
125 | struct ieee80211_sub_if_data *sdata; | 122 | struct ieee80211_sub_if_data *sdata; |
126 | struct sta_info *sta = NULL; | 123 | struct sta_info *sta = NULL; |
127 | enum ieee80211_key_alg alg; | 124 | enum ieee80211_key_alg alg; |
128 | struct ieee80211_key *key; | 125 | struct ieee80211_key *key; |
129 | int err; | 126 | int err; |
130 | 127 | ||
131 | if (dev == local->mdev) | ||
132 | return -EOPNOTSUPP; | ||
133 | |||
134 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 128 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
135 | 129 | ||
136 | switch (params->cipher) { | 130 | switch (params->cipher) { |
@@ -175,14 +169,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
175 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 169 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
176 | u8 key_idx, u8 *mac_addr) | 170 | u8 key_idx, u8 *mac_addr) |
177 | { | 171 | { |
178 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
179 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
180 | struct sta_info *sta; | 173 | struct sta_info *sta; |
181 | int ret; | 174 | int ret; |
182 | 175 | ||
183 | if (dev == local->mdev) | ||
184 | return -EOPNOTSUPP; | ||
185 | |||
186 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 176 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
187 | 177 | ||
188 | rcu_read_lock(); | 178 | rcu_read_lock(); |
@@ -223,7 +213,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
223 | void (*callback)(void *cookie, | 213 | void (*callback)(void *cookie, |
224 | struct key_params *params)) | 214 | struct key_params *params)) |
225 | { | 215 | { |
226 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
227 | struct ieee80211_sub_if_data *sdata; | 216 | struct ieee80211_sub_if_data *sdata; |
228 | struct sta_info *sta = NULL; | 217 | struct sta_info *sta = NULL; |
229 | u8 seq[6] = {0}; | 218 | u8 seq[6] = {0}; |
@@ -233,9 +222,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
233 | u16 iv16; | 222 | u16 iv16; |
234 | int err = -ENOENT; | 223 | int err = -ENOENT; |
235 | 224 | ||
236 | if (dev == local->mdev) | ||
237 | return -EOPNOTSUPP; | ||
238 | |||
239 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 225 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
240 | 226 | ||
241 | rcu_read_lock(); | 227 | rcu_read_lock(); |
@@ -311,12 +297,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
311 | struct net_device *dev, | 297 | struct net_device *dev, |
312 | u8 key_idx) | 298 | u8 key_idx) |
313 | { | 299 | { |
314 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
315 | struct ieee80211_sub_if_data *sdata; | 300 | struct ieee80211_sub_if_data *sdata; |
316 | 301 | ||
317 | if (dev == local->mdev) | ||
318 | return -EOPNOTSUPP; | ||
319 | |||
320 | rcu_read_lock(); | 302 | rcu_read_lock(); |
321 | 303 | ||
322 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 304 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -365,7 +347,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
365 | sta = sta_info_get_by_idx(local, idx, dev); | 347 | sta = sta_info_get_by_idx(local, idx, dev); |
366 | if (sta) { | 348 | if (sta) { |
367 | ret = 0; | 349 | ret = 0; |
368 | memcpy(mac, sta->addr, ETH_ALEN); | 350 | memcpy(mac, sta->sta.addr, ETH_ALEN); |
369 | sta_set_sinfo(sta, sinfo); | 351 | sta_set_sinfo(sta, sinfo); |
370 | } | 352 | } |
371 | 353 | ||
@@ -497,16 +479,12 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
497 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 479 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
498 | struct beacon_parameters *params) | 480 | struct beacon_parameters *params) |
499 | { | 481 | { |
500 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
501 | struct ieee80211_sub_if_data *sdata; | 482 | struct ieee80211_sub_if_data *sdata; |
502 | struct beacon_data *old; | 483 | struct beacon_data *old; |
503 | 484 | ||
504 | if (dev == local->mdev) | ||
505 | return -EOPNOTSUPP; | ||
506 | |||
507 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 485 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
508 | 486 | ||
509 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 487 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
510 | return -EINVAL; | 488 | return -EINVAL; |
511 | 489 | ||
512 | old = sdata->u.ap.beacon; | 490 | old = sdata->u.ap.beacon; |
@@ -520,16 +498,12 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
520 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 498 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
521 | struct beacon_parameters *params) | 499 | struct beacon_parameters *params) |
522 | { | 500 | { |
523 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
524 | struct ieee80211_sub_if_data *sdata; | 501 | struct ieee80211_sub_if_data *sdata; |
525 | struct beacon_data *old; | 502 | struct beacon_data *old; |
526 | 503 | ||
527 | if (dev == local->mdev) | ||
528 | return -EOPNOTSUPP; | ||
529 | |||
530 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 504 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
531 | 505 | ||
532 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 506 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
533 | return -EINVAL; | 507 | return -EINVAL; |
534 | 508 | ||
535 | old = sdata->u.ap.beacon; | 509 | old = sdata->u.ap.beacon; |
@@ -542,16 +516,12 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
542 | 516 | ||
543 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | 517 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) |
544 | { | 518 | { |
545 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
546 | struct ieee80211_sub_if_data *sdata; | 519 | struct ieee80211_sub_if_data *sdata; |
547 | struct beacon_data *old; | 520 | struct beacon_data *old; |
548 | 521 | ||
549 | if (dev == local->mdev) | ||
550 | return -EOPNOTSUPP; | ||
551 | |||
552 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 522 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
553 | 523 | ||
554 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 524 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
555 | return -EINVAL; | 525 | return -EINVAL; |
556 | 526 | ||
557 | old = sdata->u.ap.beacon; | 527 | old = sdata->u.ap.beacon; |
@@ -594,7 +564,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
594 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ | 564 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ |
595 | 565 | ||
596 | memset(msg->da, 0xff, ETH_ALEN); | 566 | memset(msg->da, 0xff, ETH_ALEN); |
597 | memcpy(msg->sa, sta->addr, ETH_ALEN); | 567 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
598 | msg->len = htons(6); | 568 | msg->len = htons(6); |
599 | msg->dsap = 0; | 569 | msg->dsap = 0; |
600 | msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ | 570 | msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ |
@@ -649,9 +619,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
649 | */ | 619 | */ |
650 | 620 | ||
651 | if (params->aid) { | 621 | if (params->aid) { |
652 | sta->aid = params->aid; | 622 | sta->sta.aid = params->aid; |
653 | if (sta->aid > IEEE80211_MAX_AID) | 623 | if (sta->sta.aid > IEEE80211_MAX_AID) |
654 | sta->aid = 0; /* XXX: should this be an error? */ | 624 | sta->sta.aid = 0; /* XXX: should this be an error? */ |
655 | } | 625 | } |
656 | 626 | ||
657 | if (params->listen_interval >= 0) | 627 | if (params->listen_interval >= 0) |
@@ -668,7 +638,12 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
668 | rates |= BIT(j); | 638 | rates |= BIT(j); |
669 | } | 639 | } |
670 | } | 640 | } |
671 | sta->supp_rates[local->oper_channel->band] = rates; | 641 | sta->sta.supp_rates[local->oper_channel->band] = rates; |
642 | } | ||
643 | |||
644 | if (params->ht_capa) { | ||
645 | ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, | ||
646 | &sta->sta.ht_info); | ||
672 | } | 647 | } |
673 | 648 | ||
674 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 649 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { |
@@ -691,9 +666,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
691 | struct ieee80211_sub_if_data *sdata; | 666 | struct ieee80211_sub_if_data *sdata; |
692 | int err; | 667 | int err; |
693 | 668 | ||
694 | if (dev == local->mdev || params->vlan == local->mdev) | ||
695 | return -EOPNOTSUPP; | ||
696 | |||
697 | /* Prevent a race with changing the rate control algorithm */ | 669 | /* Prevent a race with changing the rate control algorithm */ |
698 | if (!netif_running(dev)) | 670 | if (!netif_running(dev)) |
699 | return -ENETDOWN; | 671 | return -ENETDOWN; |
@@ -701,8 +673,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
701 | if (params->vlan) { | 673 | if (params->vlan) { |
702 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 674 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
703 | 675 | ||
704 | if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN && | 676 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
705 | sdata->vif.type != IEEE80211_IF_TYPE_AP) | 677 | sdata->vif.type != NL80211_IFTYPE_AP) |
706 | return -EINVAL; | 678 | return -EINVAL; |
707 | } else | 679 | } else |
708 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 680 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -721,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
721 | 693 | ||
722 | sta_apply_parameters(local, sta, params); | 694 | sta_apply_parameters(local, sta, params); |
723 | 695 | ||
724 | rate_control_rate_init(sta, local); | 696 | rate_control_rate_init(sta); |
725 | 697 | ||
726 | rcu_read_lock(); | 698 | rcu_read_lock(); |
727 | 699 | ||
@@ -732,8 +704,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
732 | return err; | 704 | return err; |
733 | } | 705 | } |
734 | 706 | ||
735 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN || | 707 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
736 | sdata->vif.type == IEEE80211_IF_TYPE_AP) | 708 | sdata->vif.type == NL80211_IFTYPE_AP) |
737 | ieee80211_send_layer2_update(sta); | 709 | ieee80211_send_layer2_update(sta); |
738 | 710 | ||
739 | rcu_read_unlock(); | 711 | rcu_read_unlock(); |
@@ -748,9 +720,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
748 | struct ieee80211_sub_if_data *sdata; | 720 | struct ieee80211_sub_if_data *sdata; |
749 | struct sta_info *sta; | 721 | struct sta_info *sta; |
750 | 722 | ||
751 | if (dev == local->mdev) | ||
752 | return -EOPNOTSUPP; | ||
753 | |||
754 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 723 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
755 | 724 | ||
756 | if (mac) { | 725 | if (mac) { |
@@ -782,9 +751,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
782 | struct sta_info *sta; | 751 | struct sta_info *sta; |
783 | struct ieee80211_sub_if_data *vlansdata; | 752 | struct ieee80211_sub_if_data *vlansdata; |
784 | 753 | ||
785 | if (dev == local->mdev || params->vlan == local->mdev) | ||
786 | return -EOPNOTSUPP; | ||
787 | |||
788 | rcu_read_lock(); | 754 | rcu_read_lock(); |
789 | 755 | ||
790 | /* XXX: get sta belonging to dev */ | 756 | /* XXX: get sta belonging to dev */ |
@@ -797,8 +763,8 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
797 | if (params->vlan && params->vlan != sta->sdata->dev) { | 763 | if (params->vlan && params->vlan != sta->sdata->dev) { |
798 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 764 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
799 | 765 | ||
800 | if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN && | 766 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
801 | vlansdata->vif.type != IEEE80211_IF_TYPE_AP) { | 767 | vlansdata->vif.type != NL80211_IFTYPE_AP) { |
802 | rcu_read_unlock(); | 768 | rcu_read_unlock(); |
803 | return -EINVAL; | 769 | return -EINVAL; |
804 | } | 770 | } |
@@ -824,15 +790,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
824 | struct sta_info *sta; | 790 | struct sta_info *sta; |
825 | int err; | 791 | int err; |
826 | 792 | ||
827 | if (dev == local->mdev) | ||
828 | return -EOPNOTSUPP; | ||
829 | |||
830 | if (!netif_running(dev)) | 793 | if (!netif_running(dev)) |
831 | return -ENETDOWN; | 794 | return -ENETDOWN; |
832 | 795 | ||
833 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 796 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
834 | 797 | ||
835 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 798 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
836 | return -ENOTSUPP; | 799 | return -ENOTSUPP; |
837 | 800 | ||
838 | rcu_read_lock(); | 801 | rcu_read_lock(); |
@@ -842,13 +805,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
842 | return -ENOENT; | 805 | return -ENOENT; |
843 | } | 806 | } |
844 | 807 | ||
845 | err = mesh_path_add(dst, dev); | 808 | err = mesh_path_add(dst, sdata); |
846 | if (err) { | 809 | if (err) { |
847 | rcu_read_unlock(); | 810 | rcu_read_unlock(); |
848 | return err; | 811 | return err; |
849 | } | 812 | } |
850 | 813 | ||
851 | mpath = mesh_path_lookup(dst, dev); | 814 | mpath = mesh_path_lookup(dst, sdata); |
852 | if (!mpath) { | 815 | if (!mpath) { |
853 | rcu_read_unlock(); | 816 | rcu_read_unlock(); |
854 | return -ENXIO; | 817 | return -ENXIO; |
@@ -862,10 +825,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
862 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | 825 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, |
863 | u8 *dst) | 826 | u8 *dst) |
864 | { | 827 | { |
828 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
829 | |||
865 | if (dst) | 830 | if (dst) |
866 | return mesh_path_del(dst, dev); | 831 | return mesh_path_del(dst, sdata); |
867 | 832 | ||
868 | mesh_path_flush(dev); | 833 | mesh_path_flush(sdata); |
869 | return 0; | 834 | return 0; |
870 | } | 835 | } |
871 | 836 | ||
@@ -878,15 +843,12 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
878 | struct mesh_path *mpath; | 843 | struct mesh_path *mpath; |
879 | struct sta_info *sta; | 844 | struct sta_info *sta; |
880 | 845 | ||
881 | if (dev == local->mdev) | ||
882 | return -EOPNOTSUPP; | ||
883 | |||
884 | if (!netif_running(dev)) | 846 | if (!netif_running(dev)) |
885 | return -ENETDOWN; | 847 | return -ENETDOWN; |
886 | 848 | ||
887 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 849 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
888 | 850 | ||
889 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 851 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
890 | return -ENOTSUPP; | 852 | return -ENOTSUPP; |
891 | 853 | ||
892 | rcu_read_lock(); | 854 | rcu_read_lock(); |
@@ -897,7 +859,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
897 | return -ENOENT; | 859 | return -ENOENT; |
898 | } | 860 | } |
899 | 861 | ||
900 | mpath = mesh_path_lookup(dst, dev); | 862 | mpath = mesh_path_lookup(dst, sdata); |
901 | if (!mpath) { | 863 | if (!mpath) { |
902 | rcu_read_unlock(); | 864 | rcu_read_unlock(); |
903 | return -ENOENT; | 865 | return -ENOENT; |
@@ -913,7 +875,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | |||
913 | struct mpath_info *pinfo) | 875 | struct mpath_info *pinfo) |
914 | { | 876 | { |
915 | if (mpath->next_hop) | 877 | if (mpath->next_hop) |
916 | memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); | 878 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); |
917 | else | 879 | else |
918 | memset(next_hop, 0, ETH_ALEN); | 880 | memset(next_hop, 0, ETH_ALEN); |
919 | 881 | ||
@@ -952,20 +914,16 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
952 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | 914 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) |
953 | 915 | ||
954 | { | 916 | { |
955 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
956 | struct ieee80211_sub_if_data *sdata; | 917 | struct ieee80211_sub_if_data *sdata; |
957 | struct mesh_path *mpath; | 918 | struct mesh_path *mpath; |
958 | 919 | ||
959 | if (dev == local->mdev) | ||
960 | return -EOPNOTSUPP; | ||
961 | |||
962 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 920 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
963 | 921 | ||
964 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 922 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
965 | return -ENOTSUPP; | 923 | return -ENOTSUPP; |
966 | 924 | ||
967 | rcu_read_lock(); | 925 | rcu_read_lock(); |
968 | mpath = mesh_path_lookup(dst, dev); | 926 | mpath = mesh_path_lookup(dst, sdata); |
969 | if (!mpath) { | 927 | if (!mpath) { |
970 | rcu_read_unlock(); | 928 | rcu_read_unlock(); |
971 | return -ENOENT; | 929 | return -ENOENT; |
@@ -980,20 +938,16 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
980 | int idx, u8 *dst, u8 *next_hop, | 938 | int idx, u8 *dst, u8 *next_hop, |
981 | struct mpath_info *pinfo) | 939 | struct mpath_info *pinfo) |
982 | { | 940 | { |
983 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
984 | struct ieee80211_sub_if_data *sdata; | 941 | struct ieee80211_sub_if_data *sdata; |
985 | struct mesh_path *mpath; | 942 | struct mesh_path *mpath; |
986 | 943 | ||
987 | if (dev == local->mdev) | ||
988 | return -EOPNOTSUPP; | ||
989 | |||
990 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 944 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
991 | 945 | ||
992 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 946 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
993 | return -ENOTSUPP; | 947 | return -ENOTSUPP; |
994 | 948 | ||
995 | rcu_read_lock(); | 949 | rcu_read_lock(); |
996 | mpath = mesh_path_lookup_by_idx(idx, dev); | 950 | mpath = mesh_path_lookup_by_idx(idx, sdata); |
997 | if (!mpath) { | 951 | if (!mpath) { |
998 | rcu_read_unlock(); | 952 | rcu_read_unlock(); |
999 | return -ENOENT; | 953 | return -ENOENT; |
@@ -1005,6 +959,38 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1005 | } | 959 | } |
1006 | #endif | 960 | #endif |
1007 | 961 | ||
962 | static int ieee80211_change_bss(struct wiphy *wiphy, | ||
963 | struct net_device *dev, | ||
964 | struct bss_parameters *params) | ||
965 | { | ||
966 | struct ieee80211_sub_if_data *sdata; | ||
967 | u32 changed = 0; | ||
968 | |||
969 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
970 | |||
971 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
972 | return -EINVAL; | ||
973 | |||
974 | if (params->use_cts_prot >= 0) { | ||
975 | sdata->bss_conf.use_cts_prot = params->use_cts_prot; | ||
976 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
977 | } | ||
978 | if (params->use_short_preamble >= 0) { | ||
979 | sdata->bss_conf.use_short_preamble = | ||
980 | params->use_short_preamble; | ||
981 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
982 | } | ||
983 | if (params->use_short_slot_time >= 0) { | ||
984 | sdata->bss_conf.use_short_slot = | ||
985 | params->use_short_slot_time; | ||
986 | changed |= BSS_CHANGED_ERP_SLOT; | ||
987 | } | ||
988 | |||
989 | ieee80211_bss_info_change_notify(sdata, changed); | ||
990 | |||
991 | return 0; | ||
992 | } | ||
993 | |||
1008 | struct cfg80211_ops mac80211_config_ops = { | 994 | struct cfg80211_ops mac80211_config_ops = { |
1009 | .add_virtual_intf = ieee80211_add_iface, | 995 | .add_virtual_intf = ieee80211_add_iface, |
1010 | .del_virtual_intf = ieee80211_del_iface, | 996 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1028,4 +1014,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1028 | .get_mpath = ieee80211_get_mpath, | 1014 | .get_mpath = ieee80211_get_mpath, |
1029 | .dump_mpath = ieee80211_dump_mpath, | 1015 | .dump_mpath = ieee80211_dump_mpath, |
1030 | #endif | 1016 | #endif |
1017 | .change_bss = ieee80211_change_bss, | ||
1031 | }; | 1018 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ee509f1109e2..24ce54463310 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -51,8 +51,6 @@ DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d", | |||
51 | local->hw.conf.antenna_sel_tx); | 51 | local->hw.conf.antenna_sel_tx); |
52 | DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", | 52 | DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", |
53 | local->hw.conf.antenna_sel_rx); | 53 | local->hw.conf.antenna_sel_rx); |
54 | DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d", | ||
55 | local->bridge_packets); | ||
56 | DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", | 54 | DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", |
57 | local->rts_threshold); | 55 | local->rts_threshold); |
58 | DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", | 56 | DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", |
@@ -206,7 +204,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
206 | DEBUGFS_ADD(frequency); | 204 | DEBUGFS_ADD(frequency); |
207 | DEBUGFS_ADD(antenna_sel_tx); | 205 | DEBUGFS_ADD(antenna_sel_tx); |
208 | DEBUGFS_ADD(antenna_sel_rx); | 206 | DEBUGFS_ADD(antenna_sel_rx); |
209 | DEBUGFS_ADD(bridge_packets); | ||
210 | DEBUGFS_ADD(rts_threshold); | 207 | DEBUGFS_ADD(rts_threshold); |
211 | DEBUGFS_ADD(fragmentation_threshold); | 208 | DEBUGFS_ADD(fragmentation_threshold); |
212 | DEBUGFS_ADD(short_retry_limit); | 209 | DEBUGFS_ADD(short_retry_limit); |
@@ -263,7 +260,6 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
263 | DEBUGFS_DEL(frequency); | 260 | DEBUGFS_DEL(frequency); |
264 | DEBUGFS_DEL(antenna_sel_tx); | 261 | DEBUGFS_DEL(antenna_sel_tx); |
265 | DEBUGFS_DEL(antenna_sel_rx); | 262 | DEBUGFS_DEL(antenna_sel_rx); |
266 | DEBUGFS_DEL(bridge_packets); | ||
267 | DEBUGFS_DEL(rts_threshold); | 263 | DEBUGFS_DEL(rts_threshold); |
268 | DEBUGFS_DEL(fragmentation_threshold); | 264 | DEBUGFS_DEL(fragmentation_threshold); |
269 | DEBUGFS_DEL(short_retry_limit); | 265 | DEBUGFS_DEL(short_retry_limit); |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index cf82acec913a..a3294d109322 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -206,7 +206,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
206 | rcu_read_lock(); | 206 | rcu_read_lock(); |
207 | sta = rcu_dereference(key->sta); | 207 | sta = rcu_dereference(key->sta); |
208 | if (sta) | 208 | if (sta) |
209 | sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr)); | 209 | sprintf(buf, "../../stations/%s", |
210 | print_mac(mac, sta->sta.addr)); | ||
210 | rcu_read_unlock(); | 211 | rcu_read_unlock(); |
211 | 212 | ||
212 | /* using sta as a boolean is fine outside RCU lock */ | 213 | /* using sta as a boolean is fine outside RCU lock */ |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8165df578c92..2ad504fc3414 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -173,7 +173,6 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC); | |||
173 | IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); | 173 | IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); |
174 | IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); | 174 | IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); |
175 | IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); | 175 | IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); |
176 | IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC); | ||
177 | 176 | ||
178 | static ssize_t ieee80211_if_fmt_flags( | 177 | static ssize_t ieee80211_if_fmt_flags( |
179 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 178 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
@@ -192,7 +191,6 @@ __IEEE80211_IF_FILE(flags); | |||
192 | /* AP attributes */ | 191 | /* AP attributes */ |
193 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 192 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
194 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 193 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
195 | IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); | ||
196 | 194 | ||
197 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( | 195 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( |
198 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 196 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
@@ -207,37 +205,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | |||
207 | 205 | ||
208 | #ifdef CONFIG_MAC80211_MESH | 206 | #ifdef CONFIG_MAC80211_MESH |
209 | /* Mesh stats attributes */ | 207 | /* Mesh stats attributes */ |
210 | IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC); | 208 | 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); | 209 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); |
212 | IEEE80211_IF_FILE(dropped_frames_no_route, | 210 | IEEE80211_IF_FILE(dropped_frames_no_route, |
213 | u.sta.mshstats.dropped_frames_no_route, DEC); | 211 | u.mesh.mshstats.dropped_frames_no_route, DEC); |
214 | IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC); | 212 | IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); |
215 | 213 | ||
216 | /* Mesh parameters */ | 214 | /* Mesh parameters */ |
217 | IEEE80211_IF_WFILE(dot11MeshMaxRetries, | 215 | IEEE80211_IF_WFILE(dot11MeshMaxRetries, |
218 | u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8); | 216 | u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8); |
219 | IEEE80211_IF_WFILE(dot11MeshRetryTimeout, | 217 | IEEE80211_IF_WFILE(dot11MeshRetryTimeout, |
220 | u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16); | 218 | u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16); |
221 | IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, | 219 | IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, |
222 | u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16); | 220 | u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16); |
223 | IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, | 221 | IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, |
224 | u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16); | 222 | u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16); |
225 | IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8); | 223 | 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); | 224 | IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8); |
227 | IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, | 225 | IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, |
228 | u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); | 226 | u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); |
229 | IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, | 227 | IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, |
230 | u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); | 228 | u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); |
231 | IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, | 229 | IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, |
232 | u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); | 230 | u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); |
233 | IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, | 231 | IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, |
234 | u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); | 232 | u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); |
235 | IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, | 233 | IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, |
236 | u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); | 234 | u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); |
237 | IEEE80211_IF_WFILE(path_refresh_time, | 235 | IEEE80211_IF_WFILE(path_refresh_time, |
238 | u.sta.mshcfg.path_refresh_time, DEC, u32); | 236 | u.mesh.mshcfg.path_refresh_time, DEC, u32); |
239 | IEEE80211_IF_WFILE(min_discovery_timeout, | 237 | IEEE80211_IF_WFILE(min_discovery_timeout, |
240 | u.sta.mshcfg.min_discovery_timeout, DEC, u16); | 238 | u.mesh.mshcfg.min_discovery_timeout, DEC, u16); |
241 | #endif | 239 | #endif |
242 | 240 | ||
243 | 241 | ||
@@ -265,7 +263,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
265 | DEBUGFS_ADD(auth_alg, sta); | 263 | DEBUGFS_ADD(auth_alg, sta); |
266 | DEBUGFS_ADD(auth_transaction, sta); | 264 | DEBUGFS_ADD(auth_transaction, sta); |
267 | DEBUGFS_ADD(flags, sta); | 265 | DEBUGFS_ADD(flags, sta); |
268 | DEBUGFS_ADD(num_beacons_sta, sta); | ||
269 | } | 266 | } |
270 | 267 | ||
271 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 268 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
@@ -276,7 +273,6 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
276 | 273 | ||
277 | DEBUGFS_ADD(num_sta_ps, ap); | 274 | DEBUGFS_ADD(num_sta_ps, ap); |
278 | DEBUGFS_ADD(dtim_count, ap); | 275 | DEBUGFS_ADD(dtim_count, ap); |
279 | DEBUGFS_ADD(num_beacons, ap); | ||
280 | DEBUGFS_ADD(num_buffered_multicast, ap); | 276 | DEBUGFS_ADD(num_buffered_multicast, ap); |
281 | } | 277 | } |
282 | 278 | ||
@@ -345,26 +341,26 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
345 | return; | 341 | return; |
346 | 342 | ||
347 | switch (sdata->vif.type) { | 343 | switch (sdata->vif.type) { |
348 | case IEEE80211_IF_TYPE_MESH_POINT: | 344 | case NL80211_IFTYPE_MESH_POINT: |
349 | #ifdef CONFIG_MAC80211_MESH | 345 | #ifdef CONFIG_MAC80211_MESH |
350 | add_mesh_stats(sdata); | 346 | add_mesh_stats(sdata); |
351 | add_mesh_config(sdata); | 347 | add_mesh_config(sdata); |
352 | #endif | 348 | #endif |
353 | /* fall through */ | 349 | break; |
354 | case IEEE80211_IF_TYPE_STA: | 350 | case NL80211_IFTYPE_STATION: |
355 | case IEEE80211_IF_TYPE_IBSS: | 351 | case NL80211_IFTYPE_ADHOC: |
356 | add_sta_files(sdata); | 352 | add_sta_files(sdata); |
357 | break; | 353 | break; |
358 | case IEEE80211_IF_TYPE_AP: | 354 | case NL80211_IFTYPE_AP: |
359 | add_ap_files(sdata); | 355 | add_ap_files(sdata); |
360 | break; | 356 | break; |
361 | case IEEE80211_IF_TYPE_WDS: | 357 | case NL80211_IFTYPE_WDS: |
362 | add_wds_files(sdata); | 358 | add_wds_files(sdata); |
363 | break; | 359 | break; |
364 | case IEEE80211_IF_TYPE_MNTR: | 360 | case NL80211_IFTYPE_MONITOR: |
365 | add_monitor_files(sdata); | 361 | add_monitor_files(sdata); |
366 | break; | 362 | break; |
367 | case IEEE80211_IF_TYPE_VLAN: | 363 | case NL80211_IFTYPE_AP_VLAN: |
368 | add_vlan_files(sdata); | 364 | add_vlan_files(sdata); |
369 | break; | 365 | break; |
370 | default: | 366 | default: |
@@ -398,7 +394,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) | |||
398 | DEBUGFS_DEL(auth_alg, sta); | 394 | DEBUGFS_DEL(auth_alg, sta); |
399 | DEBUGFS_DEL(auth_transaction, sta); | 395 | DEBUGFS_DEL(auth_transaction, sta); |
400 | DEBUGFS_DEL(flags, sta); | 396 | DEBUGFS_DEL(flags, sta); |
401 | DEBUGFS_DEL(num_beacons_sta, sta); | ||
402 | } | 397 | } |
403 | 398 | ||
404 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) | 399 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) |
@@ -409,7 +404,6 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata) | |||
409 | 404 | ||
410 | DEBUGFS_DEL(num_sta_ps, ap); | 405 | DEBUGFS_DEL(num_sta_ps, ap); |
411 | DEBUGFS_DEL(dtim_count, ap); | 406 | DEBUGFS_DEL(dtim_count, ap); |
412 | DEBUGFS_DEL(num_beacons, ap); | ||
413 | DEBUGFS_DEL(num_buffered_multicast, ap); | 407 | DEBUGFS_DEL(num_buffered_multicast, ap); |
414 | } | 408 | } |
415 | 409 | ||
@@ -482,26 +476,26 @@ static void del_files(struct ieee80211_sub_if_data *sdata) | |||
482 | return; | 476 | return; |
483 | 477 | ||
484 | switch (sdata->vif.type) { | 478 | switch (sdata->vif.type) { |
485 | case IEEE80211_IF_TYPE_MESH_POINT: | 479 | case NL80211_IFTYPE_MESH_POINT: |
486 | #ifdef CONFIG_MAC80211_MESH | 480 | #ifdef CONFIG_MAC80211_MESH |
487 | del_mesh_stats(sdata); | 481 | del_mesh_stats(sdata); |
488 | del_mesh_config(sdata); | 482 | del_mesh_config(sdata); |
489 | #endif | 483 | #endif |
490 | /* fall through */ | 484 | break; |
491 | case IEEE80211_IF_TYPE_STA: | 485 | case NL80211_IFTYPE_STATION: |
492 | case IEEE80211_IF_TYPE_IBSS: | 486 | case NL80211_IFTYPE_ADHOC: |
493 | del_sta_files(sdata); | 487 | del_sta_files(sdata); |
494 | break; | 488 | break; |
495 | case IEEE80211_IF_TYPE_AP: | 489 | case NL80211_IFTYPE_AP: |
496 | del_ap_files(sdata); | 490 | del_ap_files(sdata); |
497 | break; | 491 | break; |
498 | case IEEE80211_IF_TYPE_WDS: | 492 | case NL80211_IFTYPE_WDS: |
499 | del_wds_files(sdata); | 493 | del_wds_files(sdata); |
500 | break; | 494 | break; |
501 | case IEEE80211_IF_TYPE_MNTR: | 495 | case NL80211_IFTYPE_MONITOR: |
502 | del_monitor_files(sdata); | 496 | del_monitor_files(sdata); |
503 | break; | 497 | break; |
504 | case IEEE80211_IF_TYPE_VLAN: | 498 | case NL80211_IFTYPE_AP_VLAN: |
505 | del_vlan_files(sdata); | 499 | del_vlan_files(sdata); |
506 | break; | 500 | break; |
507 | default: | 501 | default: |
@@ -551,8 +545,12 @@ static int netdev_notify(struct notifier_block *nb, | |||
551 | 545 | ||
552 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 546 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
553 | 547 | ||
554 | sprintf(buf, "netdev:%s", dev->name); | ||
555 | dir = sdata->debugfsdir; | 548 | dir = sdata->debugfsdir; |
549 | |||
550 | if (!dir) | ||
551 | return 0; | ||
552 | |||
553 | sprintf(buf, "netdev:%s", dev->name); | ||
556 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 554 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
557 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 555 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " |
558 | "dir to %s\n", buf); | 556 | "dir to %s\n", buf); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 79a062782d52..189d0bafa91a 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -50,7 +50,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
50 | STA_READ_##format(name, field) \ | 50 | STA_READ_##format(name, field) \ |
51 | STA_OPS(name) | 51 | STA_OPS(name) |
52 | 52 | ||
53 | STA_FILE(aid, aid, D); | 53 | STA_FILE(aid, sta.aid, D); |
54 | STA_FILE(dev, sdata->dev->name, S); | 54 | STA_FILE(dev, sdata->dev->name, S); |
55 | STA_FILE(rx_packets, rx_packets, LU); | 55 | STA_FILE(rx_packets, rx_packets, LU); |
56 | STA_FILE(tx_packets, tx_packets, LU); | 56 | STA_FILE(tx_packets, tx_packets, LU); |
@@ -173,10 +173,9 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
173 | const char __user *user_buf, size_t count, loff_t *ppos) | 173 | const char __user *user_buf, size_t count, loff_t *ppos) |
174 | { | 174 | { |
175 | struct sta_info *sta = file->private_data; | 175 | struct sta_info *sta = file->private_data; |
176 | struct net_device *dev = sta->sdata->dev; | 176 | struct ieee80211_local *local = sta->sdata->local; |
177 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
178 | struct ieee80211_hw *hw = &local->hw; | 177 | struct ieee80211_hw *hw = &local->hw; |
179 | u8 *da = sta->addr; | 178 | u8 *da = sta->sta.addr; |
180 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, | 179 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, |
181 | 0, 0, 0, 0, 0, 0, 0, 0}; | 180 | 0, 0, 0, 0, 0, 0, 0, 0}; |
182 | static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1, | 181 | static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1, |
@@ -201,7 +200,7 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
201 | tid_num = tid_num - 100; | 200 | tid_num = tid_num - 100; |
202 | if (tid_static_rx[tid_num] == 1) { | 201 | if (tid_static_rx[tid_num] == 1) { |
203 | strcpy(state, "off "); | 202 | strcpy(state, "off "); |
204 | ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0, | 203 | ieee80211_sta_stop_rx_ba_session(sta->sdata, da, tid_num, 0, |
205 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 204 | WLAN_REASON_QSTA_REQUIRE_SETUP); |
206 | sta->ampdu_mlme.tid_state_rx[tid_num] |= | 205 | sta->ampdu_mlme.tid_state_rx[tid_num] |= |
207 | HT_AGG_STATE_DEBUGFS_CTL; | 206 | HT_AGG_STATE_DEBUGFS_CTL; |
@@ -250,11 +249,22 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
250 | DECLARE_MAC_BUF(mbuf); | 249 | DECLARE_MAC_BUF(mbuf); |
251 | u8 *mac; | 250 | u8 *mac; |
252 | 251 | ||
252 | sta->debugfs.add_has_run = true; | ||
253 | |||
253 | if (!stations_dir) | 254 | if (!stations_dir) |
254 | return; | 255 | return; |
255 | 256 | ||
256 | mac = print_mac(mbuf, sta->addr); | 257 | mac = print_mac(mbuf, sta->sta.addr); |
257 | 258 | ||
259 | /* | ||
260 | * This might fail due to a race condition: | ||
261 | * When mac80211 unlinks a station, the debugfs entries | ||
262 | * remain, but it is already possible to link a new | ||
263 | * station with the same address which triggers adding | ||
264 | * it to debugfs; therefore, if the old station isn't | ||
265 | * destroyed quickly enough the old station's debugfs | ||
266 | * dir might still be around. | ||
267 | */ | ||
258 | sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); | 268 | sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); |
259 | if (!sta->debugfs.dir) | 269 | if (!sta->debugfs.dir) |
260 | return; | 270 | return; |
diff --git a/net/mac80211/event.c b/net/mac80211/event.c index 2280f40b4560..8de60de70bc9 100644 --- a/net/mac80211/event.c +++ b/net/mac80211/event.c | |||
@@ -8,7 +8,6 @@ | |||
8 | * mac80211 - events | 8 | * mac80211 - events |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <net/iw_handler.h> | 11 | #include <net/iw_handler.h> |
13 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
14 | 13 | ||
@@ -17,7 +16,7 @@ | |||
17 | * (in the variable hdr) must be long enough to extract the TKIP | 16 | * (in the variable hdr) must be long enough to extract the TKIP |
18 | * fields like TSC | 17 | * fields like TSC |
19 | */ | 18 | */ |
20 | void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | 19 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
21 | struct ieee80211_hdr *hdr) | 20 | struct ieee80211_hdr *hdr) |
22 | { | 21 | { |
23 | union iwreq_data wrqu; | 22 | union iwreq_data wrqu; |
@@ -32,7 +31,7 @@ void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | |||
32 | print_mac(mac, hdr->addr2)); | 31 | print_mac(mac, hdr->addr2)); |
33 | memset(&wrqu, 0, sizeof(wrqu)); | 32 | memset(&wrqu, 0, sizeof(wrqu)); |
34 | wrqu.data.length = strlen(buf); | 33 | wrqu.data.length = strlen(buf); |
35 | wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); | 34 | wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); |
36 | kfree(buf); | 35 | kfree(buf); |
37 | } | 36 | } |
38 | 37 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c new file mode 100644 index 000000000000..dc7d9a3d70d5 --- /dev/null +++ b/net/mac80211/ht.c | |||
@@ -0,0 +1,992 @@ | |||
1 | /* | ||
2 | * HT handling | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2007-2008, Intel Corporation | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/ieee80211.h> | ||
17 | #include <net/wireless.h> | ||
18 | #include <net/mac80211.h> | ||
19 | #include "ieee80211_i.h" | ||
20 | #include "sta_info.h" | ||
21 | #include "wme.h" | ||
22 | |||
23 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
24 | struct ieee80211_ht_info *ht_info) | ||
25 | { | ||
26 | |||
27 | if (ht_info == NULL) | ||
28 | return -EINVAL; | ||
29 | |||
30 | memset(ht_info, 0, sizeof(*ht_info)); | ||
31 | |||
32 | if (ht_cap_ie) { | ||
33 | u8 ampdu_info = ht_cap_ie->ampdu_params_info; | ||
34 | |||
35 | ht_info->ht_supported = 1; | ||
36 | ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); | ||
37 | ht_info->ampdu_factor = | ||
38 | ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; | ||
39 | ht_info->ampdu_density = | ||
40 | (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; | ||
41 | memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); | ||
42 | } else | ||
43 | ht_info->ht_supported = 0; | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
49 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
50 | struct ieee80211_ht_bss_info *bss_info) | ||
51 | { | ||
52 | if (bss_info == NULL) | ||
53 | return -EINVAL; | ||
54 | |||
55 | memset(bss_info, 0, sizeof(*bss_info)); | ||
56 | |||
57 | if (ht_add_info_ie) { | ||
58 | u16 op_mode; | ||
59 | op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); | ||
60 | |||
61 | bss_info->primary_channel = ht_add_info_ie->control_chan; | ||
62 | bss_info->bss_cap = ht_add_info_ie->ht_param; | ||
63 | bss_info->bss_op_mode = (u8)(op_mode & 0xff); | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | ||
70 | const u8 *da, u16 tid, | ||
71 | u8 dialog_token, u16 start_seq_num, | ||
72 | u16 agg_size, u16 timeout) | ||
73 | { | ||
74 | struct ieee80211_local *local = sdata->local; | ||
75 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
76 | struct sk_buff *skb; | ||
77 | struct ieee80211_mgmt *mgmt; | ||
78 | u16 capab; | ||
79 | |||
80 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
81 | |||
82 | if (!skb) { | ||
83 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
84 | "for addba request frame\n", sdata->dev->name); | ||
85 | return; | ||
86 | } | ||
87 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
88 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
89 | memset(mgmt, 0, 24); | ||
90 | memcpy(mgmt->da, da, ETH_ALEN); | ||
91 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
92 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
93 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
94 | else | ||
95 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
96 | |||
97 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
98 | IEEE80211_STYPE_ACTION); | ||
99 | |||
100 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); | ||
101 | |||
102 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
103 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | ||
104 | |||
105 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | ||
106 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
107 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
108 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | ||
109 | |||
110 | mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); | ||
111 | |||
112 | mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); | ||
113 | mgmt->u.action.u.addba_req.start_seq_num = | ||
114 | cpu_to_le16(start_seq_num << 4); | ||
115 | |||
116 | ieee80211_tx_skb(sdata, skb, 0); | ||
117 | } | ||
118 | |||
119 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | ||
120 | u8 dialog_token, u16 status, u16 policy, | ||
121 | u16 buf_size, u16 timeout) | ||
122 | { | ||
123 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
124 | struct ieee80211_local *local = sdata->local; | ||
125 | struct sk_buff *skb; | ||
126 | struct ieee80211_mgmt *mgmt; | ||
127 | u16 capab; | ||
128 | |||
129 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
130 | |||
131 | if (!skb) { | ||
132 | printk(KERN_DEBUG "%s: failed to allocate buffer " | ||
133 | "for addba resp frame\n", sdata->dev->name); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
138 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
139 | memset(mgmt, 0, 24); | ||
140 | memcpy(mgmt->da, da, ETH_ALEN); | ||
141 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
142 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
143 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
144 | else | ||
145 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
146 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
147 | IEEE80211_STYPE_ACTION); | ||
148 | |||
149 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); | ||
150 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
151 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | ||
152 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | ||
153 | |||
154 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | ||
155 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
156 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | ||
157 | |||
158 | mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); | ||
159 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | ||
160 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | ||
161 | |||
162 | ieee80211_tx_skb(sdata, skb, 0); | ||
163 | } | ||
164 | |||
165 | static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | ||
166 | const u8 *da, u16 tid, | ||
167 | u16 initiator, u16 reason_code) | ||
168 | { | ||
169 | struct ieee80211_local *local = sdata->local; | ||
170 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
171 | struct sk_buff *skb; | ||
172 | struct ieee80211_mgmt *mgmt; | ||
173 | u16 params; | ||
174 | |||
175 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
176 | |||
177 | if (!skb) { | ||
178 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
179 | "for delba frame\n", sdata->dev->name); | ||
180 | return; | ||
181 | } | ||
182 | |||
183 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
184 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
185 | memset(mgmt, 0, 24); | ||
186 | memcpy(mgmt->da, da, ETH_ALEN); | ||
187 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
188 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
189 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
190 | else | ||
191 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
192 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
193 | IEEE80211_STYPE_ACTION); | ||
194 | |||
195 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); | ||
196 | |||
197 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
198 | mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | ||
199 | params = (u16)(initiator << 11); /* bit 11 initiator */ | ||
200 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | ||
201 | |||
202 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | ||
203 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | ||
204 | |||
205 | ieee80211_tx_skb(sdata, skb, 0); | ||
206 | } | ||
207 | |||
208 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | ||
209 | { | ||
210 | struct ieee80211_local *local = sdata->local; | ||
211 | struct sk_buff *skb; | ||
212 | struct ieee80211_bar *bar; | ||
213 | u16 bar_control = 0; | ||
214 | |||
215 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | ||
216 | if (!skb) { | ||
217 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
218 | "bar frame\n", sdata->dev->name); | ||
219 | return; | ||
220 | } | ||
221 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
222 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
223 | memset(bar, 0, sizeof(*bar)); | ||
224 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
225 | IEEE80211_STYPE_BACK_REQ); | ||
226 | memcpy(bar->ra, ra, ETH_ALEN); | ||
227 | memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); | ||
228 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
229 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
230 | bar_control |= (u16)(tid << 12); | ||
231 | bar->control = cpu_to_le16(bar_control); | ||
232 | bar->start_seq_num = cpu_to_le16(ssn); | ||
233 | |||
234 | ieee80211_tx_skb(sdata, skb, 0); | ||
235 | } | ||
236 | |||
237 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | ||
238 | u16 initiator, u16 reason) | ||
239 | { | ||
240 | struct ieee80211_local *local = sdata->local; | ||
241 | struct ieee80211_hw *hw = &local->hw; | ||
242 | struct sta_info *sta; | ||
243 | int ret, i; | ||
244 | DECLARE_MAC_BUF(mac); | ||
245 | |||
246 | rcu_read_lock(); | ||
247 | |||
248 | sta = sta_info_get(local, ra); | ||
249 | if (!sta) { | ||
250 | rcu_read_unlock(); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | /* check if TID is in operational state */ | ||
255 | spin_lock_bh(&sta->lock); | ||
256 | if (sta->ampdu_mlme.tid_state_rx[tid] | ||
257 | != HT_AGG_STATE_OPERATIONAL) { | ||
258 | spin_unlock_bh(&sta->lock); | ||
259 | rcu_read_unlock(); | ||
260 | return; | ||
261 | } | ||
262 | sta->ampdu_mlme.tid_state_rx[tid] = | ||
263 | HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
264 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
265 | spin_unlock_bh(&sta->lock); | ||
266 | |||
267 | /* stop HW Rx aggregation. ampdu_action existence | ||
268 | * already verified in session init so we add the BUG_ON */ | ||
269 | BUG_ON(!local->ops->ampdu_action); | ||
270 | |||
271 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
272 | printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", | ||
273 | print_mac(mac, ra), tid); | ||
274 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
275 | |||
276 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | ||
277 | &sta->sta, tid, NULL); | ||
278 | if (ret) | ||
279 | printk(KERN_DEBUG "HW problem - can not stop rx " | ||
280 | "aggregation for tid %d\n", tid); | ||
281 | |||
282 | /* shutdown timer has not expired */ | ||
283 | if (initiator != WLAN_BACK_TIMER) | ||
284 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
285 | |||
286 | /* check if this is a self generated aggregation halt */ | ||
287 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | ||
288 | ieee80211_send_delba(sdata, ra, tid, 0, reason); | ||
289 | |||
290 | /* free the reordering buffer */ | ||
291 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | ||
292 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | ||
293 | /* release the reordered frames */ | ||
294 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | ||
295 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | ||
296 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | ||
297 | } | ||
298 | } | ||
299 | /* free resources */ | ||
300 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
301 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
302 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
303 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
304 | |||
305 | rcu_read_unlock(); | ||
306 | } | ||
307 | |||
308 | |||
309 | /* | ||
310 | * After sending add Block Ack request we activated a timer until | ||
311 | * add Block Ack response will arrive from the recipient. | ||
312 | * If this timer expires sta_addba_resp_timer_expired will be executed. | ||
313 | */ | ||
314 | static void sta_addba_resp_timer_expired(unsigned long data) | ||
315 | { | ||
316 | /* not an elegant detour, but there is no choice as the timer passes | ||
317 | * only one argument, and both sta_info and TID are needed, so init | ||
318 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
319 | * array gives the sta through container_of */ | ||
320 | u16 tid = *(u8 *)data; | ||
321 | struct sta_info *temp_sta = container_of((void *)data, | ||
322 | struct sta_info, timer_to_tid[tid]); | ||
323 | |||
324 | struct ieee80211_local *local = temp_sta->local; | ||
325 | struct ieee80211_hw *hw = &local->hw; | ||
326 | struct sta_info *sta; | ||
327 | u8 *state; | ||
328 | |||
329 | rcu_read_lock(); | ||
330 | |||
331 | sta = sta_info_get(local, temp_sta->sta.addr); | ||
332 | if (!sta) { | ||
333 | rcu_read_unlock(); | ||
334 | return; | ||
335 | } | ||
336 | |||
337 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
338 | /* check if the TID waits for addBA response */ | ||
339 | spin_lock_bh(&sta->lock); | ||
340 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
341 | spin_unlock_bh(&sta->lock); | ||
342 | *state = HT_AGG_STATE_IDLE; | ||
343 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
344 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | ||
345 | "expecting addBA response there", tid); | ||
346 | #endif | ||
347 | goto timer_expired_exit; | ||
348 | } | ||
349 | |||
350 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
351 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
352 | #endif | ||
353 | |||
354 | /* go through the state check in stop_BA_session */ | ||
355 | *state = HT_AGG_STATE_OPERATIONAL; | ||
356 | spin_unlock_bh(&sta->lock); | ||
357 | ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid, | ||
358 | WLAN_BACK_INITIATOR); | ||
359 | |||
360 | timer_expired_exit: | ||
361 | rcu_read_unlock(); | ||
362 | } | ||
363 | |||
364 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) | ||
365 | { | ||
366 | struct ieee80211_local *local = sdata->local; | ||
367 | int i; | ||
368 | |||
369 | for (i = 0; i < STA_TID_NUM; i++) { | ||
370 | ieee80211_stop_tx_ba_session(&local->hw, addr, i, | ||
371 | WLAN_BACK_INITIATOR); | ||
372 | ieee80211_sta_stop_rx_ba_session(sdata, addr, i, | ||
373 | WLAN_BACK_RECIPIENT, | ||
374 | WLAN_REASON_QSTA_LEAVE_QBSS); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
379 | { | ||
380 | struct ieee80211_local *local = hw_to_local(hw); | ||
381 | struct sta_info *sta; | ||
382 | struct ieee80211_sub_if_data *sdata; | ||
383 | u16 start_seq_num; | ||
384 | u8 *state; | ||
385 | int ret; | ||
386 | DECLARE_MAC_BUF(mac); | ||
387 | |||
388 | if (tid >= STA_TID_NUM) | ||
389 | return -EINVAL; | ||
390 | |||
391 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
392 | printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", | ||
393 | print_mac(mac, ra), tid); | ||
394 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
395 | |||
396 | rcu_read_lock(); | ||
397 | |||
398 | sta = sta_info_get(local, ra); | ||
399 | if (!sta) { | ||
400 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
401 | printk(KERN_DEBUG "Could not find the station\n"); | ||
402 | #endif | ||
403 | ret = -ENOENT; | ||
404 | goto exit; | ||
405 | } | ||
406 | |||
407 | spin_lock_bh(&sta->lock); | ||
408 | |||
409 | /* we have tried too many times, receiver does not want A-MPDU */ | ||
410 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | ||
411 | ret = -EBUSY; | ||
412 | goto err_unlock_sta; | ||
413 | } | ||
414 | |||
415 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
416 | /* check if the TID is not in aggregation flow already */ | ||
417 | if (*state != HT_AGG_STATE_IDLE) { | ||
418 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
419 | printk(KERN_DEBUG "BA request denied - session is not " | ||
420 | "idle on tid %u\n", tid); | ||
421 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
422 | ret = -EAGAIN; | ||
423 | goto err_unlock_sta; | ||
424 | } | ||
425 | |||
426 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
427 | sta->ampdu_mlme.tid_tx[tid] = | ||
428 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
429 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
430 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
431 | if (net_ratelimit()) | ||
432 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
433 | tid); | ||
434 | #endif | ||
435 | ret = -ENOMEM; | ||
436 | goto err_unlock_sta; | ||
437 | } | ||
438 | /* Tx timer */ | ||
439 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
440 | sta_addba_resp_timer_expired; | ||
441 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
442 | (unsigned long)&sta->timer_to_tid[tid]; | ||
443 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
444 | |||
445 | /* create a new queue for this aggregation */ | ||
446 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
447 | |||
448 | /* case no queue is available to aggregation | ||
449 | * don't switch to aggregation */ | ||
450 | if (ret) { | ||
451 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
452 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | ||
453 | " tid %d\n", tid); | ||
454 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
455 | goto err_unlock_queue; | ||
456 | } | ||
457 | sdata = sta->sdata; | ||
458 | |||
459 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
460 | * call back right away, it must see that the flow has begun */ | ||
461 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
462 | |||
463 | /* This is slightly racy because the queue isn't stopped */ | ||
464 | start_seq_num = sta->tid_seq[tid]; | ||
465 | |||
466 | if (local->ops->ampdu_action) | ||
467 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | ||
468 | &sta->sta, tid, &start_seq_num); | ||
469 | |||
470 | if (ret) { | ||
471 | /* No need to requeue the packets in the agg queue, since we | ||
472 | * held the tx lock: no packet could be enqueued to the newly | ||
473 | * allocated queue */ | ||
474 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
475 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
476 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
477 | " tid %d\n", tid); | ||
478 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
479 | *state = HT_AGG_STATE_IDLE; | ||
480 | goto err_unlock_queue; | ||
481 | } | ||
482 | |||
483 | /* Will put all the packets in the new SW queue */ | ||
484 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
485 | spin_unlock_bh(&sta->lock); | ||
486 | |||
487 | /* send an addBA request */ | ||
488 | sta->ampdu_mlme.dialog_token_allocator++; | ||
489 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | ||
490 | sta->ampdu_mlme.dialog_token_allocator; | ||
491 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
492 | |||
493 | |||
494 | ieee80211_send_addba_request(sta->sdata, ra, tid, | ||
495 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | ||
496 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
497 | 0x40, 5000); | ||
498 | /* activate the timer for the recipient's addBA response */ | ||
499 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
500 | jiffies + ADDBA_RESP_INTERVAL; | ||
501 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
502 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
503 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
504 | #endif | ||
505 | goto exit; | ||
506 | |||
507 | err_unlock_queue: | ||
508 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
509 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
510 | ret = -EBUSY; | ||
511 | err_unlock_sta: | ||
512 | spin_unlock_bh(&sta->lock); | ||
513 | exit: | ||
514 | rcu_read_unlock(); | ||
515 | return ret; | ||
516 | } | ||
517 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
518 | |||
519 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | ||
520 | u8 *ra, u16 tid, | ||
521 | enum ieee80211_back_parties initiator) | ||
522 | { | ||
523 | struct ieee80211_local *local = hw_to_local(hw); | ||
524 | struct sta_info *sta; | ||
525 | u8 *state; | ||
526 | int ret = 0; | ||
527 | DECLARE_MAC_BUF(mac); | ||
528 | |||
529 | if (tid >= STA_TID_NUM) | ||
530 | return -EINVAL; | ||
531 | |||
532 | rcu_read_lock(); | ||
533 | sta = sta_info_get(local, ra); | ||
534 | if (!sta) { | ||
535 | rcu_read_unlock(); | ||
536 | return -ENOENT; | ||
537 | } | ||
538 | |||
539 | /* check if the TID is in aggregation */ | ||
540 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
541 | spin_lock_bh(&sta->lock); | ||
542 | |||
543 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
544 | ret = -ENOENT; | ||
545 | goto stop_BA_exit; | ||
546 | } | ||
547 | |||
548 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
549 | printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", | ||
550 | print_mac(mac, ra), tid); | ||
551 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
552 | |||
553 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
554 | |||
555 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
556 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
557 | |||
558 | if (local->ops->ampdu_action) | ||
559 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, | ||
560 | &sta->sta, tid, NULL); | ||
561 | |||
562 | /* case HW denied going back to legacy */ | ||
563 | if (ret) { | ||
564 | WARN_ON(ret != -EBUSY); | ||
565 | *state = HT_AGG_STATE_OPERATIONAL; | ||
566 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
567 | goto stop_BA_exit; | ||
568 | } | ||
569 | |||
570 | stop_BA_exit: | ||
571 | spin_unlock_bh(&sta->lock); | ||
572 | rcu_read_unlock(); | ||
573 | return ret; | ||
574 | } | ||
575 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
576 | |||
577 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
578 | { | ||
579 | struct ieee80211_local *local = hw_to_local(hw); | ||
580 | struct sta_info *sta; | ||
581 | u8 *state; | ||
582 | DECLARE_MAC_BUF(mac); | ||
583 | |||
584 | if (tid >= STA_TID_NUM) { | ||
585 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
586 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
587 | tid, STA_TID_NUM); | ||
588 | #endif | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | rcu_read_lock(); | ||
593 | sta = sta_info_get(local, ra); | ||
594 | if (!sta) { | ||
595 | rcu_read_unlock(); | ||
596 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
597 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
598 | print_mac(mac, ra)); | ||
599 | #endif | ||
600 | return; | ||
601 | } | ||
602 | |||
603 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
604 | spin_lock_bh(&sta->lock); | ||
605 | |||
606 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
607 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
608 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | ||
609 | *state); | ||
610 | #endif | ||
611 | spin_unlock_bh(&sta->lock); | ||
612 | rcu_read_unlock(); | ||
613 | return; | ||
614 | } | ||
615 | |||
616 | WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); | ||
617 | |||
618 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
619 | |||
620 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
621 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
622 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | ||
623 | #endif | ||
624 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
625 | } | ||
626 | spin_unlock_bh(&sta->lock); | ||
627 | rcu_read_unlock(); | ||
628 | } | ||
629 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
630 | |||
631 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | ||
632 | { | ||
633 | struct ieee80211_local *local = hw_to_local(hw); | ||
634 | struct sta_info *sta; | ||
635 | u8 *state; | ||
636 | int agg_queue; | ||
637 | DECLARE_MAC_BUF(mac); | ||
638 | |||
639 | if (tid >= STA_TID_NUM) { | ||
640 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
641 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
642 | tid, STA_TID_NUM); | ||
643 | #endif | ||
644 | return; | ||
645 | } | ||
646 | |||
647 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
648 | printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", | ||
649 | print_mac(mac, ra), tid); | ||
650 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
651 | |||
652 | rcu_read_lock(); | ||
653 | sta = sta_info_get(local, ra); | ||
654 | if (!sta) { | ||
655 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
656 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
657 | print_mac(mac, ra)); | ||
658 | #endif | ||
659 | rcu_read_unlock(); | ||
660 | return; | ||
661 | } | ||
662 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
663 | |||
664 | /* NOTE: no need to use sta->lock in this state check, as | ||
665 | * ieee80211_stop_tx_ba_session will let only one stop call to | ||
666 | * pass through per sta/tid | ||
667 | */ | ||
668 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | ||
669 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
670 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
671 | #endif | ||
672 | rcu_read_unlock(); | ||
673 | return; | ||
674 | } | ||
675 | |||
676 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | ||
677 | ieee80211_send_delba(sta->sdata, ra, tid, | ||
678 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | ||
679 | |||
680 | agg_queue = sta->tid_to_tx_q[tid]; | ||
681 | |||
682 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | ||
683 | |||
684 | /* We just requeued the all the frames that were in the | ||
685 | * removed queue, and since we might miss a softirq we do | ||
686 | * netif_schedule_queue. ieee80211_wake_queue is not used | ||
687 | * here as this queue is not necessarily stopped | ||
688 | */ | ||
689 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); | ||
690 | spin_lock_bh(&sta->lock); | ||
691 | *state = HT_AGG_STATE_IDLE; | ||
692 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
693 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
694 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
695 | spin_unlock_bh(&sta->lock); | ||
696 | |||
697 | rcu_read_unlock(); | ||
698 | } | ||
699 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
700 | |||
701 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
702 | const u8 *ra, u16 tid) | ||
703 | { | ||
704 | struct ieee80211_local *local = hw_to_local(hw); | ||
705 | struct ieee80211_ra_tid *ra_tid; | ||
706 | struct sk_buff *skb = dev_alloc_skb(0); | ||
707 | |||
708 | if (unlikely(!skb)) { | ||
709 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
710 | if (net_ratelimit()) | ||
711 | printk(KERN_WARNING "%s: Not enough memory, " | ||
712 | "dropping start BA session", skb->dev->name); | ||
713 | #endif | ||
714 | return; | ||
715 | } | ||
716 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
717 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
718 | ra_tid->tid = tid; | ||
719 | |||
720 | skb->pkt_type = IEEE80211_ADDBA_MSG; | ||
721 | skb_queue_tail(&local->skb_queue, skb); | ||
722 | tasklet_schedule(&local->tasklet); | ||
723 | } | ||
724 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
725 | |||
726 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
727 | const u8 *ra, u16 tid) | ||
728 | { | ||
729 | struct ieee80211_local *local = hw_to_local(hw); | ||
730 | struct ieee80211_ra_tid *ra_tid; | ||
731 | struct sk_buff *skb = dev_alloc_skb(0); | ||
732 | |||
733 | if (unlikely(!skb)) { | ||
734 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
735 | if (net_ratelimit()) | ||
736 | printk(KERN_WARNING "%s: Not enough memory, " | ||
737 | "dropping stop BA session", skb->dev->name); | ||
738 | #endif | ||
739 | return; | ||
740 | } | ||
741 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
742 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
743 | ra_tid->tid = tid; | ||
744 | |||
745 | skb->pkt_type = IEEE80211_DELBA_MSG; | ||
746 | skb_queue_tail(&local->skb_queue, skb); | ||
747 | tasklet_schedule(&local->tasklet); | ||
748 | } | ||
749 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
750 | |||
751 | /* | ||
752 | * After accepting the AddBA Request we activated a timer, | ||
753 | * resetting it after each frame that arrives from the originator. | ||
754 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
755 | */ | ||
756 | static void sta_rx_agg_session_timer_expired(unsigned long data) | ||
757 | { | ||
758 | /* not an elegant detour, but there is no choice as the timer passes | ||
759 | * only one argument, and various sta_info are needed here, so init | ||
760 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
761 | * array gives the sta through container_of */ | ||
762 | u8 *ptid = (u8 *)data; | ||
763 | u8 *timer_to_id = ptid - *ptid; | ||
764 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
765 | timer_to_tid[0]); | ||
766 | |||
767 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
768 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | ||
769 | #endif | ||
770 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | ||
771 | (u16)*ptid, WLAN_BACK_TIMER, | ||
772 | WLAN_REASON_QSTA_TIMEOUT); | ||
773 | } | ||
774 | |||
775 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
776 | struct sta_info *sta, | ||
777 | struct ieee80211_mgmt *mgmt, | ||
778 | size_t len) | ||
779 | { | ||
780 | struct ieee80211_hw *hw = &local->hw; | ||
781 | struct ieee80211_conf *conf = &hw->conf; | ||
782 | struct tid_ampdu_rx *tid_agg_rx; | ||
783 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | ||
784 | u8 dialog_token; | ||
785 | int ret = -EOPNOTSUPP; | ||
786 | DECLARE_MAC_BUF(mac); | ||
787 | |||
788 | /* extract session parameters from addba request frame */ | ||
789 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
790 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
791 | start_seq_num = | ||
792 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
793 | |||
794 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
795 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
796 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
797 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
798 | |||
799 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
800 | |||
801 | /* sanity check for incoming parameters: | ||
802 | * check if configuration can support the BA policy | ||
803 | * and if buffer size does not exceeds max value */ | ||
804 | if (((ba_policy != 1) | ||
805 | && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) | ||
806 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | ||
807 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
808 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
809 | if (net_ratelimit()) | ||
810 | printk(KERN_DEBUG "AddBA Req with bad params from " | ||
811 | "%s on tid %u. policy %d, buffer size %d\n", | ||
812 | print_mac(mac, mgmt->sa), tid, ba_policy, | ||
813 | buf_size); | ||
814 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
815 | goto end_no_lock; | ||
816 | } | ||
817 | /* determine default buffer size */ | ||
818 | if (buf_size == 0) { | ||
819 | struct ieee80211_supported_band *sband; | ||
820 | |||
821 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
822 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
823 | buf_size = buf_size << sband->ht_info.ampdu_factor; | ||
824 | } | ||
825 | |||
826 | |||
827 | /* examine state machine */ | ||
828 | spin_lock_bh(&sta->lock); | ||
829 | |||
830 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | ||
831 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
832 | if (net_ratelimit()) | ||
833 | printk(KERN_DEBUG "unexpected AddBA Req from " | ||
834 | "%s on tid %u\n", | ||
835 | print_mac(mac, mgmt->sa), tid); | ||
836 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
837 | goto end; | ||
838 | } | ||
839 | |||
840 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
841 | sta->ampdu_mlme.tid_rx[tid] = | ||
842 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
843 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
844 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
845 | if (net_ratelimit()) | ||
846 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
847 | tid); | ||
848 | #endif | ||
849 | goto end; | ||
850 | } | ||
851 | /* rx timer */ | ||
852 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
853 | sta_rx_agg_session_timer_expired; | ||
854 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
855 | (unsigned long)&sta->timer_to_tid[tid]; | ||
856 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
857 | |||
858 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
859 | |||
860 | /* prepare reordering buffer */ | ||
861 | tid_agg_rx->reorder_buf = | ||
862 | kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); | ||
863 | if (!tid_agg_rx->reorder_buf) { | ||
864 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
865 | if (net_ratelimit()) | ||
866 | printk(KERN_ERR "can not allocate reordering buffer " | ||
867 | "to tid %d\n", tid); | ||
868 | #endif | ||
869 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
870 | goto end; | ||
871 | } | ||
872 | memset(tid_agg_rx->reorder_buf, 0, | ||
873 | buf_size * sizeof(struct sk_buff *)); | ||
874 | |||
875 | if (local->ops->ampdu_action) | ||
876 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | ||
877 | &sta->sta, tid, &start_seq_num); | ||
878 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
879 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
880 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
881 | |||
882 | if (ret) { | ||
883 | kfree(tid_agg_rx->reorder_buf); | ||
884 | kfree(tid_agg_rx); | ||
885 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
886 | goto end; | ||
887 | } | ||
888 | |||
889 | /* change state and send addba resp */ | ||
890 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | ||
891 | tid_agg_rx->dialog_token = dialog_token; | ||
892 | tid_agg_rx->ssn = start_seq_num; | ||
893 | tid_agg_rx->head_seq_num = start_seq_num; | ||
894 | tid_agg_rx->buf_size = buf_size; | ||
895 | tid_agg_rx->timeout = timeout; | ||
896 | tid_agg_rx->stored_mpdu_num = 0; | ||
897 | status = WLAN_STATUS_SUCCESS; | ||
898 | end: | ||
899 | spin_unlock_bh(&sta->lock); | ||
900 | |||
901 | end_no_lock: | ||
902 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | ||
903 | dialog_token, status, 1, buf_size, timeout); | ||
904 | } | ||
905 | |||
906 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | ||
907 | struct sta_info *sta, | ||
908 | struct ieee80211_mgmt *mgmt, | ||
909 | size_t len) | ||
910 | { | ||
911 | struct ieee80211_hw *hw = &local->hw; | ||
912 | u16 capab; | ||
913 | u16 tid; | ||
914 | u8 *state; | ||
915 | |||
916 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | ||
917 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
918 | |||
919 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
920 | |||
921 | spin_lock_bh(&sta->lock); | ||
922 | |||
923 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
924 | spin_unlock_bh(&sta->lock); | ||
925 | return; | ||
926 | } | ||
927 | |||
928 | if (mgmt->u.action.u.addba_resp.dialog_token != | ||
929 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | ||
930 | spin_unlock_bh(&sta->lock); | ||
931 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
932 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
933 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
934 | return; | ||
935 | } | ||
936 | |||
937 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
938 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
939 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | ||
940 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
941 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | ||
942 | == WLAN_STATUS_SUCCESS) { | ||
943 | *state |= HT_ADDBA_RECEIVED_MSK; | ||
944 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
945 | |||
946 | if (*state == HT_AGG_STATE_OPERATIONAL) | ||
947 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
948 | |||
949 | spin_unlock_bh(&sta->lock); | ||
950 | } else { | ||
951 | sta->ampdu_mlme.addba_req_num[tid]++; | ||
952 | /* this will allow the state check in stop_BA_session */ | ||
953 | *state = HT_AGG_STATE_OPERATIONAL; | ||
954 | spin_unlock_bh(&sta->lock); | ||
955 | ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid, | ||
956 | WLAN_BACK_INITIATOR); | ||
957 | } | ||
958 | } | ||
959 | |||
960 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | ||
961 | struct sta_info *sta, | ||
962 | struct ieee80211_mgmt *mgmt, size_t len) | ||
963 | { | ||
964 | struct ieee80211_local *local = sdata->local; | ||
965 | u16 tid, params; | ||
966 | u16 initiator; | ||
967 | DECLARE_MAC_BUF(mac); | ||
968 | |||
969 | params = le16_to_cpu(mgmt->u.action.u.delba.params); | ||
970 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; | ||
971 | initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11; | ||
972 | |||
973 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
974 | if (net_ratelimit()) | ||
975 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", | ||
976 | print_mac(mac, mgmt->sa), | ||
977 | initiator ? "initiator" : "recipient", tid, | ||
978 | mgmt->u.action.u.delba.reason_code); | ||
979 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
980 | |||
981 | if (initiator == WLAN_BACK_INITIATOR) | ||
982 | ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid, | ||
983 | WLAN_BACK_INITIATOR, 0); | ||
984 | else { /* WLAN_BACK_RECIPIENT */ | ||
985 | spin_lock_bh(&sta->lock); | ||
986 | sta->ampdu_mlme.tid_state_tx[tid] = | ||
987 | HT_AGG_STATE_OPERATIONAL; | ||
988 | spin_unlock_bh(&sta->lock); | ||
989 | ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid, | ||
990 | WLAN_BACK_RECIPIENT); | ||
991 | } | ||
992 | } | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4498d8713652..156e42a003ae 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -29,17 +29,6 @@ | |||
29 | #include "key.h" | 29 | #include "key.h" |
30 | #include "sta_info.h" | 30 | #include "sta_info.h" |
31 | 31 | ||
32 | /* ieee80211.o internal definitions, etc. These are not included into | ||
33 | * low-level drivers. */ | ||
34 | |||
35 | #ifndef ETH_P_PAE | ||
36 | #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ | ||
37 | #endif /* ETH_P_PAE */ | ||
38 | |||
39 | #define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08) | ||
40 | |||
41 | #define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype) | ||
42 | |||
43 | struct ieee80211_local; | 32 | struct ieee80211_local; |
44 | 33 | ||
45 | /* Maximum number of broadcast/multicast frames to buffer when some of the | 34 | /* Maximum number of broadcast/multicast frames to buffer when some of the |
@@ -61,6 +50,12 @@ struct ieee80211_local; | |||
61 | * increased memory use (about 2 kB of RAM per entry). */ | 50 | * increased memory use (about 2 kB of RAM per entry). */ |
62 | #define IEEE80211_FRAGMENT_MAX 4 | 51 | #define IEEE80211_FRAGMENT_MAX 4 |
63 | 52 | ||
53 | /* | ||
54 | * Time after which we ignore scan results and no longer report/use | ||
55 | * them in any way. | ||
56 | */ | ||
57 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | ||
58 | |||
64 | struct ieee80211_fragment_entry { | 59 | struct ieee80211_fragment_entry { |
65 | unsigned long first_frag_time; | 60 | unsigned long first_frag_time; |
66 | unsigned int seq; | 61 | unsigned int seq; |
@@ -73,9 +68,9 @@ struct ieee80211_fragment_entry { | |||
73 | }; | 68 | }; |
74 | 69 | ||
75 | 70 | ||
76 | struct ieee80211_sta_bss { | 71 | struct ieee80211_bss { |
77 | struct list_head list; | 72 | struct list_head list; |
78 | struct ieee80211_sta_bss *hnext; | 73 | struct ieee80211_bss *hnext; |
79 | size_t ssid_len; | 74 | size_t ssid_len; |
80 | 75 | ||
81 | atomic_t users; | 76 | atomic_t users; |
@@ -87,16 +82,11 @@ struct ieee80211_sta_bss { | |||
87 | enum ieee80211_band band; | 82 | enum ieee80211_band band; |
88 | int freq; | 83 | int freq; |
89 | int signal, noise, qual; | 84 | int signal, noise, qual; |
90 | u8 *wpa_ie; | 85 | u8 *ies; /* all information elements from the last Beacon or Probe |
91 | size_t wpa_ie_len; | 86 | * Response frames; note Beacon frame is not allowed to |
92 | u8 *rsn_ie; | 87 | * override values from Probe Response */ |
93 | size_t rsn_ie_len; | 88 | size_t ies_len; |
94 | u8 *wmm_ie; | 89 | bool wmm_used; |
95 | size_t wmm_ie_len; | ||
96 | u8 *ht_ie; | ||
97 | size_t ht_ie_len; | ||
98 | u8 *ht_add_ie; | ||
99 | size_t ht_add_ie_len; | ||
100 | #ifdef CONFIG_MAC80211_MESH | 90 | #ifdef CONFIG_MAC80211_MESH |
101 | u8 *mesh_id; | 91 | u8 *mesh_id; |
102 | size_t mesh_id_len; | 92 | size_t mesh_id_len; |
@@ -108,7 +98,7 @@ struct ieee80211_sta_bss { | |||
108 | u64 timestamp; | 98 | u64 timestamp; |
109 | int beacon_int; | 99 | int beacon_int; |
110 | 100 | ||
111 | bool probe_resp; | 101 | unsigned long last_probe_resp; |
112 | unsigned long last_update; | 102 | unsigned long last_update; |
113 | 103 | ||
114 | /* during assocation, we save an ERP value from a probe response so | 104 | /* during assocation, we save an ERP value from a probe response so |
@@ -119,7 +109,7 @@ struct ieee80211_sta_bss { | |||
119 | u8 erp_value; | 109 | u8 erp_value; |
120 | }; | 110 | }; |
121 | 111 | ||
122 | static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) | 112 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) |
123 | { | 113 | { |
124 | #ifdef CONFIG_MAC80211_MESH | 114 | #ifdef CONFIG_MAC80211_MESH |
125 | return bss->mesh_cfg; | 115 | return bss->mesh_cfg; |
@@ -127,7 +117,7 @@ static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) | |||
127 | return NULL; | 117 | return NULL; |
128 | } | 118 | } |
129 | 119 | ||
130 | static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) | 120 | static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) |
131 | { | 121 | { |
132 | #ifdef CONFIG_MAC80211_MESH | 122 | #ifdef CONFIG_MAC80211_MESH |
133 | return bss->mesh_id; | 123 | return bss->mesh_id; |
@@ -135,7 +125,7 @@ static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) | |||
135 | return NULL; | 125 | return NULL; |
136 | } | 126 | } |
137 | 127 | ||
138 | static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss) | 128 | static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) |
139 | { | 129 | { |
140 | #ifdef CONFIG_MAC80211_MESH | 130 | #ifdef CONFIG_MAC80211_MESH |
141 | return bss->mesh_id_len; | 131 | return bss->mesh_id_len; |
@@ -174,7 +164,7 @@ struct ieee80211_tx_data { | |||
174 | struct sk_buff **extra_frag; | 164 | struct sk_buff **extra_frag; |
175 | int num_extra_frag; | 165 | int num_extra_frag; |
176 | 166 | ||
177 | u16 fc, ethertype; | 167 | u16 ethertype; |
178 | unsigned int flags; | 168 | unsigned int flags; |
179 | }; | 169 | }; |
180 | 170 | ||
@@ -202,7 +192,7 @@ struct ieee80211_rx_data { | |||
202 | struct ieee80211_rx_status *status; | 192 | struct ieee80211_rx_status *status; |
203 | struct ieee80211_rate *rate; | 193 | struct ieee80211_rate *rate; |
204 | 194 | ||
205 | u16 fc, ethertype; | 195 | u16 ethertype; |
206 | unsigned int flags; | 196 | unsigned int flags; |
207 | int sent_ps_buffered; | 197 | int sent_ps_buffered; |
208 | int queue; | 198 | int queue; |
@@ -239,7 +229,6 @@ struct ieee80211_if_ap { | |||
239 | struct sk_buff_head ps_bc_buf; | 229 | struct sk_buff_head ps_bc_buf; |
240 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 230 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
241 | int dtim_count; | 231 | int dtim_count; |
242 | int num_beacons; /* number of TXed beacon frames for this BSS */ | ||
243 | }; | 232 | }; |
244 | 233 | ||
245 | struct ieee80211_if_wds { | 234 | struct ieee80211_if_wds { |
@@ -300,48 +289,37 @@ struct mesh_config { | |||
300 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) | 289 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) |
301 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) | 290 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) |
302 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) | 291 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) |
292 | /* flags for MLME request */ | ||
293 | #define IEEE80211_STA_REQ_SCAN 0 | ||
294 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 | ||
295 | #define IEEE80211_STA_REQ_AUTH 2 | ||
296 | #define IEEE80211_STA_REQ_RUN 3 | ||
297 | |||
298 | /* STA/IBSS MLME states */ | ||
299 | enum ieee80211_sta_mlme_state { | ||
300 | IEEE80211_STA_MLME_DISABLED, | ||
301 | IEEE80211_STA_MLME_DIRECT_PROBE, | ||
302 | IEEE80211_STA_MLME_AUTHENTICATE, | ||
303 | IEEE80211_STA_MLME_ASSOCIATE, | ||
304 | IEEE80211_STA_MLME_ASSOCIATED, | ||
305 | IEEE80211_STA_MLME_IBSS_SEARCH, | ||
306 | IEEE80211_STA_MLME_IBSS_JOINED, | ||
307 | }; | ||
308 | |||
309 | /* bitfield of allowed auth algs */ | ||
310 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | ||
311 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | ||
312 | #define IEEE80211_AUTH_ALG_LEAP BIT(2) | ||
313 | |||
303 | struct ieee80211_if_sta { | 314 | struct ieee80211_if_sta { |
304 | struct timer_list timer; | 315 | struct timer_list timer; |
305 | struct work_struct work; | 316 | struct work_struct work; |
306 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | 317 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; |
307 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 318 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
308 | enum { | 319 | enum ieee80211_sta_mlme_state state; |
309 | IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, | ||
310 | IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, | ||
311 | IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, | ||
312 | IEEE80211_MESH_UP | ||
313 | } state; | ||
314 | size_t ssid_len; | 320 | size_t ssid_len; |
315 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 321 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
316 | size_t scan_ssid_len; | 322 | size_t scan_ssid_len; |
317 | #ifdef CONFIG_MAC80211_MESH | ||
318 | struct timer_list mesh_path_timer; | ||
319 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | ||
320 | size_t mesh_id_len; | ||
321 | /* Active Path Selection Protocol Identifier */ | ||
322 | u8 mesh_pp_id[4]; | ||
323 | /* Active Path Selection Metric Identifier */ | ||
324 | u8 mesh_pm_id[4]; | ||
325 | /* Congestion Control Mode Identifier */ | ||
326 | u8 mesh_cc_id[4]; | ||
327 | /* Local mesh Destination Sequence Number */ | ||
328 | u32 dsn; | ||
329 | /* Last used PREQ ID */ | ||
330 | u32 preq_id; | ||
331 | atomic_t mpaths; | ||
332 | /* Timestamp of last DSN update */ | ||
333 | unsigned long last_dsn_update; | ||
334 | /* Timestamp of last DSN sent */ | ||
335 | unsigned long last_preq; | ||
336 | struct mesh_rmc *rmc; | ||
337 | spinlock_t mesh_preq_queue_lock; | ||
338 | struct mesh_preq_queue preq_queue; | ||
339 | int preq_queue_len; | ||
340 | struct mesh_stats mshstats; | ||
341 | struct mesh_config mshcfg; | ||
342 | u32 mesh_seqnum; | ||
343 | bool accepting_plinks; | ||
344 | #endif | ||
345 | u16 aid; | 323 | u16 aid; |
346 | u16 ap_capab, capab; | 324 | u16 ap_capab, capab; |
347 | u8 *extra_ie; /* to be added to the end of AssocReq */ | 325 | u8 *extra_ie; /* to be added to the end of AssocReq */ |
@@ -353,20 +331,17 @@ struct ieee80211_if_sta { | |||
353 | 331 | ||
354 | struct sk_buff_head skb_queue; | 332 | struct sk_buff_head skb_queue; |
355 | 333 | ||
356 | int auth_tries, assoc_tries; | 334 | int assoc_scan_tries; /* number of scans done pre-association */ |
335 | int direct_probe_tries; /* retries for direct probes */ | ||
336 | int auth_tries; /* retries for auth req */ | ||
337 | int assoc_tries; /* retries for assoc req */ | ||
357 | 338 | ||
358 | unsigned long request; | 339 | unsigned long request; |
359 | 340 | ||
360 | unsigned long last_probe; | 341 | unsigned long last_probe; |
361 | 342 | ||
362 | unsigned int flags; | 343 | unsigned int flags; |
363 | #define IEEE80211_STA_REQ_SCAN 0 | ||
364 | #define IEEE80211_STA_REQ_AUTH 1 | ||
365 | #define IEEE80211_STA_REQ_RUN 2 | ||
366 | 344 | ||
367 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | ||
368 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | ||
369 | #define IEEE80211_AUTH_ALG_LEAP BIT(2) | ||
370 | unsigned int auth_algs; /* bitfield of allowed auth algs */ | 345 | unsigned int auth_algs; /* bitfield of allowed auth algs */ |
371 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ | 346 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ |
372 | int auth_transaction; | 347 | int auth_transaction; |
@@ -376,31 +351,70 @@ struct ieee80211_if_sta { | |||
376 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; | 351 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; |
377 | 352 | ||
378 | int wmm_last_param_set; | 353 | int wmm_last_param_set; |
379 | int num_beacons; /* number of TXed beacon frames by this STA */ | ||
380 | }; | 354 | }; |
381 | 355 | ||
382 | static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta, | 356 | struct ieee80211_if_mesh { |
383 | u8 mesh_id_len, u8 *mesh_id) | 357 | struct work_struct work; |
384 | { | 358 | struct timer_list housekeeping_timer; |
385 | #ifdef CONFIG_MAC80211_MESH | 359 | struct timer_list mesh_path_timer; |
386 | ifsta->mesh_id_len = mesh_id_len; | 360 | struct sk_buff_head skb_queue; |
387 | memcpy(ifsta->mesh_id, mesh_id, mesh_id_len); | 361 | |
388 | #endif | 362 | bool housekeeping; |
389 | } | 363 | |
364 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | ||
365 | size_t mesh_id_len; | ||
366 | /* Active Path Selection Protocol Identifier */ | ||
367 | u8 mesh_pp_id[4]; | ||
368 | /* Active Path Selection Metric Identifier */ | ||
369 | u8 mesh_pm_id[4]; | ||
370 | /* Congestion Control Mode Identifier */ | ||
371 | u8 mesh_cc_id[4]; | ||
372 | /* Local mesh Destination Sequence Number */ | ||
373 | u32 dsn; | ||
374 | /* Last used PREQ ID */ | ||
375 | u32 preq_id; | ||
376 | atomic_t mpaths; | ||
377 | /* Timestamp of last DSN update */ | ||
378 | unsigned long last_dsn_update; | ||
379 | /* Timestamp of last DSN sent */ | ||
380 | unsigned long last_preq; | ||
381 | struct mesh_rmc *rmc; | ||
382 | spinlock_t mesh_preq_queue_lock; | ||
383 | struct mesh_preq_queue preq_queue; | ||
384 | int preq_queue_len; | ||
385 | struct mesh_stats mshstats; | ||
386 | struct mesh_config mshcfg; | ||
387 | u32 mesh_seqnum; | ||
388 | bool accepting_plinks; | ||
389 | }; | ||
390 | 390 | ||
391 | #ifdef CONFIG_MAC80211_MESH | 391 | #ifdef CONFIG_MAC80211_MESH |
392 | #define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ | 392 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
393 | do { (sta)->mshstats.name++; } while (0) | 393 | do { (msh)->mshstats.name++; } while (0) |
394 | #else | 394 | #else |
395 | #define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ | 395 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
396 | do { } while (0) | 396 | do { } while (0) |
397 | #endif | 397 | #endif |
398 | 398 | ||
399 | /* flags used in struct ieee80211_sub_if_data.flags */ | 399 | /** |
400 | #define IEEE80211_SDATA_ALLMULTI BIT(0) | 400 | * enum ieee80211_sub_if_data_flags - virtual interface flags |
401 | #define IEEE80211_SDATA_PROMISC BIT(1) | 401 | * |
402 | #define IEEE80211_SDATA_USERSPACE_MLME BIT(2) | 402 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets |
403 | #define IEEE80211_SDATA_OPERATING_GMODE BIT(3) | 403 | * @IEEE80211_SDATA_PROMISC: interface is promisc |
404 | * @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active | ||
405 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode | ||
406 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | ||
407 | * associated stations and deliver multicast frames both | ||
408 | * back to wireless media and to the local net stack. | ||
409 | */ | ||
410 | enum ieee80211_sub_if_data_flags { | ||
411 | IEEE80211_SDATA_ALLMULTI = BIT(0), | ||
412 | IEEE80211_SDATA_PROMISC = BIT(1), | ||
413 | IEEE80211_SDATA_USERSPACE_MLME = BIT(2), | ||
414 | IEEE80211_SDATA_OPERATING_GMODE = BIT(3), | ||
415 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4), | ||
416 | }; | ||
417 | |||
404 | struct ieee80211_sub_if_data { | 418 | struct ieee80211_sub_if_data { |
405 | struct list_head list; | 419 | struct list_head list; |
406 | 420 | ||
@@ -416,11 +430,6 @@ struct ieee80211_sub_if_data { | |||
416 | 430 | ||
417 | int drop_unencrypted; | 431 | int drop_unencrypted; |
418 | 432 | ||
419 | /* | ||
420 | * basic rates of this AP or the AP we're associated to | ||
421 | */ | ||
422 | u64 basic_rates; | ||
423 | |||
424 | /* Fragment table for host-based reassembly */ | 433 | /* Fragment table for host-based reassembly */ |
425 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 434 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
426 | unsigned int fragment_next; | 435 | unsigned int fragment_next; |
@@ -447,6 +456,9 @@ struct ieee80211_sub_if_data { | |||
447 | struct ieee80211_if_wds wds; | 456 | struct ieee80211_if_wds wds; |
448 | struct ieee80211_if_vlan vlan; | 457 | struct ieee80211_if_vlan vlan; |
449 | struct ieee80211_if_sta sta; | 458 | struct ieee80211_if_sta sta; |
459 | #ifdef CONFIG_MAC80211_MESH | ||
460 | struct ieee80211_if_mesh mesh; | ||
461 | #endif | ||
450 | u32 mntr_flags; | 462 | u32 mntr_flags; |
451 | } u; | 463 | } u; |
452 | 464 | ||
@@ -469,7 +481,6 @@ struct ieee80211_sub_if_data { | |||
469 | struct dentry *auth_alg; | 481 | struct dentry *auth_alg; |
470 | struct dentry *auth_transaction; | 482 | struct dentry *auth_transaction; |
471 | struct dentry *flags; | 483 | struct dentry *flags; |
472 | struct dentry *num_beacons_sta; | ||
473 | struct dentry *force_unicast_rateidx; | 484 | struct dentry *force_unicast_rateidx; |
474 | struct dentry *max_ratectrl_rateidx; | 485 | struct dentry *max_ratectrl_rateidx; |
475 | } sta; | 486 | } sta; |
@@ -477,7 +488,6 @@ struct ieee80211_sub_if_data { | |||
477 | struct dentry *drop_unencrypted; | 488 | struct dentry *drop_unencrypted; |
478 | struct dentry *num_sta_ps; | 489 | struct dentry *num_sta_ps; |
479 | struct dentry *dtim_count; | 490 | struct dentry *dtim_count; |
480 | struct dentry *num_beacons; | ||
481 | struct dentry *force_unicast_rateidx; | 491 | struct dentry *force_unicast_rateidx; |
482 | struct dentry *max_ratectrl_rateidx; | 492 | struct dentry *max_ratectrl_rateidx; |
483 | struct dentry *num_buffered_multicast; | 493 | struct dentry *num_buffered_multicast; |
@@ -540,6 +550,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
540 | return container_of(p, struct ieee80211_sub_if_data, vif); | 550 | return container_of(p, struct ieee80211_sub_if_data, vif); |
541 | } | 551 | } |
542 | 552 | ||
553 | static inline void | ||
554 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | ||
555 | u8 mesh_id_len, u8 *mesh_id) | ||
556 | { | ||
557 | #ifdef CONFIG_MAC80211_MESH | ||
558 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
559 | ifmsh->mesh_id_len = mesh_id_len; | ||
560 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | ||
561 | #else | ||
562 | WARN_ON(1); | ||
563 | #endif | ||
564 | } | ||
565 | |||
543 | enum { | 566 | enum { |
544 | IEEE80211_RX_MSG = 1, | 567 | IEEE80211_RX_MSG = 1, |
545 | IEEE80211_TX_STATUS_MSG = 2, | 568 | IEEE80211_TX_STATUS_MSG = 2, |
@@ -550,6 +573,10 @@ enum { | |||
550 | /* maximum number of hardware queues we support. */ | 573 | /* maximum number of hardware queues we support. */ |
551 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) | 574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
552 | 575 | ||
576 | struct ieee80211_master_priv { | ||
577 | struct ieee80211_local *local; | ||
578 | }; | ||
579 | |||
553 | struct ieee80211_local { | 580 | struct ieee80211_local { |
554 | /* embed the driver visible part. | 581 | /* embed the driver visible part. |
555 | * don't cast (use the static inlines below), but we keep | 582 | * don't cast (use the static inlines below), but we keep |
@@ -613,10 +640,6 @@ struct ieee80211_local { | |||
613 | struct crypto_blkcipher *wep_rx_tfm; | 640 | struct crypto_blkcipher *wep_rx_tfm; |
614 | u32 wep_iv; | 641 | u32 wep_iv; |
615 | 642 | ||
616 | int bridge_packets; /* bridge packets between associated stations and | ||
617 | * deliver multicast frames both back to wireless | ||
618 | * media and to the local net stack */ | ||
619 | |||
620 | struct list_head interfaces; | 643 | struct list_head interfaces; |
621 | 644 | ||
622 | /* | 645 | /* |
@@ -626,21 +649,21 @@ struct ieee80211_local { | |||
626 | spinlock_t key_lock; | 649 | spinlock_t key_lock; |
627 | 650 | ||
628 | 651 | ||
629 | bool sta_sw_scanning; | 652 | /* Scanning and BSS list */ |
630 | bool sta_hw_scanning; | 653 | bool sw_scanning, hw_scanning; |
631 | int scan_channel_idx; | 654 | int scan_channel_idx; |
632 | enum ieee80211_band scan_band; | 655 | enum ieee80211_band scan_band; |
633 | 656 | ||
634 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; | 657 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; |
635 | unsigned long last_scan_completed; | 658 | unsigned long last_scan_completed; |
636 | struct delayed_work scan_work; | 659 | struct delayed_work scan_work; |
637 | struct net_device *scan_dev; | 660 | struct ieee80211_sub_if_data *scan_sdata; |
638 | struct ieee80211_channel *oper_channel, *scan_channel; | 661 | struct ieee80211_channel *oper_channel, *scan_channel; |
639 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 662 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
640 | size_t scan_ssid_len; | 663 | size_t scan_ssid_len; |
641 | struct list_head sta_bss_list; | 664 | struct list_head bss_list; |
642 | struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE]; | 665 | struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; |
643 | spinlock_t sta_bss_lock; | 666 | spinlock_t bss_lock; |
644 | 667 | ||
645 | /* SNMP counters */ | 668 | /* SNMP counters */ |
646 | /* dot11CountersTable */ | 669 | /* dot11CountersTable */ |
@@ -701,10 +724,11 @@ struct ieee80211_local { | |||
701 | 724 | ||
702 | #ifdef CONFIG_MAC80211_DEBUGFS | 725 | #ifdef CONFIG_MAC80211_DEBUGFS |
703 | struct local_debugfsdentries { | 726 | struct local_debugfsdentries { |
727 | struct dentry *rcdir; | ||
728 | struct dentry *rcname; | ||
704 | struct dentry *frequency; | 729 | struct dentry *frequency; |
705 | struct dentry *antenna_sel_tx; | 730 | struct dentry *antenna_sel_tx; |
706 | struct dentry *antenna_sel_rx; | 731 | struct dentry *antenna_sel_rx; |
707 | struct dentry *bridge_packets; | ||
708 | struct dentry *rts_threshold; | 732 | struct dentry *rts_threshold; |
709 | struct dentry *fragmentation_threshold; | 733 | struct dentry *fragmentation_threshold; |
710 | struct dentry *short_retry_limit; | 734 | struct dentry *short_retry_limit; |
@@ -774,6 +798,9 @@ struct ieee80211_ra_tid { | |||
774 | 798 | ||
775 | /* Parsed Information Elements */ | 799 | /* Parsed Information Elements */ |
776 | struct ieee802_11_elems { | 800 | struct ieee802_11_elems { |
801 | u8 *ie_start; | ||
802 | size_t total_len; | ||
803 | |||
777 | /* pointers to IEs */ | 804 | /* pointers to IEs */ |
778 | u8 *ssid; | 805 | u8 *ssid; |
779 | u8 *supp_rates; | 806 | u8 *supp_rates; |
@@ -789,8 +816,8 @@ struct ieee802_11_elems { | |||
789 | u8 *ext_supp_rates; | 816 | u8 *ext_supp_rates; |
790 | u8 *wmm_info; | 817 | u8 *wmm_info; |
791 | u8 *wmm_param; | 818 | u8 *wmm_param; |
792 | u8 *ht_cap_elem; | 819 | struct ieee80211_ht_cap *ht_cap_elem; |
793 | u8 *ht_info_elem; | 820 | struct ieee80211_ht_addt_info *ht_info_elem; |
794 | u8 *mesh_config; | 821 | u8 *mesh_config; |
795 | u8 *mesh_id; | 822 | u8 *mesh_id; |
796 | u8 *peer_link; | 823 | u8 *peer_link; |
@@ -817,8 +844,6 @@ struct ieee802_11_elems { | |||
817 | u8 ext_supp_rates_len; | 844 | u8 ext_supp_rates_len; |
818 | u8 wmm_info_len; | 845 | u8 wmm_info_len; |
819 | u8 wmm_param_len; | 846 | u8 wmm_param_len; |
820 | u8 ht_cap_elem_len; | ||
821 | u8 ht_info_elem_len; | ||
822 | u8 mesh_config_len; | 847 | u8 mesh_config_len; |
823 | u8 mesh_id_len; | 848 | u8 mesh_id_len; |
824 | u8 peer_link_len; | 849 | u8 peer_link_len; |
@@ -857,86 +882,82 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
857 | } | 882 | } |
858 | 883 | ||
859 | 884 | ||
860 | /* ieee80211.c */ | ||
861 | int ieee80211_hw_config(struct ieee80211_local *local); | 885 | int ieee80211_hw_config(struct ieee80211_local *local); |
862 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); | 886 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); |
863 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 887 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
864 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | 888 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, |
865 | struct ieee80211_ht_info *req_ht_cap, | 889 | struct ieee80211_ht_info *req_ht_cap, |
866 | struct ieee80211_ht_bss_info *req_bss_cap); | 890 | struct ieee80211_ht_bss_info *req_bss_cap); |
891 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | ||
892 | u32 changed); | ||
893 | void ieee80211_configure_filter(struct ieee80211_local *local); | ||
867 | 894 | ||
868 | /* ieee80211_ioctl.c */ | 895 | /* wireless extensions */ |
869 | extern const struct iw_handler_def ieee80211_iw_handler_def; | 896 | extern const struct iw_handler_def ieee80211_iw_handler_def; |
870 | int ieee80211_set_freq(struct net_device *dev, int freq); | ||
871 | 897 | ||
872 | /* ieee80211_sta.c */ | 898 | /* STA/IBSS code */ |
873 | void ieee80211_sta_timer(unsigned long data); | 899 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
874 | void ieee80211_sta_work(struct work_struct *work); | 900 | void ieee80211_scan_work(struct work_struct *work); |
875 | void ieee80211_sta_scan_work(struct work_struct *work); | 901 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
876 | void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | ||
877 | struct ieee80211_rx_status *rx_status); | 902 | struct ieee80211_rx_status *rx_status); |
878 | int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); | 903 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); |
879 | int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len); | 904 | int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); |
880 | int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); | 905 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); |
881 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); | 906 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, |
882 | void ieee80211_sta_req_auth(struct net_device *dev, | ||
883 | struct ieee80211_if_sta *ifsta); | 907 | struct ieee80211_if_sta *ifsta); |
884 | int ieee80211_sta_scan_results(struct net_device *dev, | 908 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
885 | struct iw_request_info *info, | ||
886 | char *buf, size_t len); | ||
887 | ieee80211_rx_result ieee80211_sta_rx_scan( | ||
888 | struct net_device *dev, struct sk_buff *skb, | ||
889 | struct ieee80211_rx_status *rx_status); | ||
890 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); | ||
891 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); | ||
892 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); | ||
893 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | ||
894 | struct sk_buff *skb, u8 *bssid, | 909 | struct sk_buff *skb, u8 *bssid, |
895 | u8 *addr, u64 supp_rates); | 910 | u8 *addr, u64 supp_rates); |
896 | int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); | 911 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); |
897 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); | 912 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); |
898 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 913 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
899 | u32 changed); | ||
900 | u32 ieee80211_reset_erp_info(struct net_device *dev); | ||
901 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
902 | struct ieee80211_ht_info *ht_info); | ||
903 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
904 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
905 | struct ieee80211_ht_bss_info *bss_info); | ||
906 | void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | ||
907 | u16 tid, u8 dialog_token, u16 start_seq_num, | ||
908 | u16 agg_size, u16 timeout); | ||
909 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | ||
910 | u16 initiator, u16 reason_code); | ||
911 | void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn); | ||
912 | |||
913 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, | ||
914 | u16 tid, u16 initiator, u16 reason); | ||
915 | void sta_addba_resp_timer_expired(unsigned long data); | ||
916 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); | ||
917 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 914 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
918 | struct ieee802_11_elems *elems, | 915 | struct ieee802_11_elems *elems, |
919 | enum ieee80211_band band); | 916 | enum ieee80211_band band); |
920 | void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | 917 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
921 | int encrypt); | 918 | u8 *ssid, size_t ssid_len); |
922 | void ieee802_11_parse_elems(u8 *start, size_t len, | 919 | |
923 | struct ieee802_11_elems *elems); | 920 | /* scan/BSS handling */ |
924 | 921 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |
925 | #ifdef CONFIG_MAC80211_MESH | 922 | u8 *ssid, size_t ssid_len); |
926 | void ieee80211_start_mesh(struct net_device *dev); | 923 | int ieee80211_scan_results(struct ieee80211_local *local, |
927 | #else | 924 | struct iw_request_info *info, |
928 | static inline void ieee80211_start_mesh(struct net_device *dev) | 925 | char *buf, size_t len); |
929 | {} | 926 | ieee80211_rx_result |
930 | #endif | 927 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, |
928 | struct sk_buff *skb, | ||
929 | struct ieee80211_rx_status *rx_status); | ||
930 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); | ||
931 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); | ||
932 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | ||
933 | char *ie, size_t len); | ||
934 | |||
935 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | ||
936 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | ||
937 | u8 *ssid, size_t ssid_len); | ||
938 | struct ieee80211_bss * | ||
939 | ieee80211_bss_info_update(struct ieee80211_local *local, | ||
940 | struct ieee80211_rx_status *rx_status, | ||
941 | struct ieee80211_mgmt *mgmt, | ||
942 | size_t len, | ||
943 | struct ieee802_11_elems *elems, | ||
944 | int freq, bool beacon); | ||
945 | struct ieee80211_bss * | ||
946 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
947 | u8 *ssid, u8 ssid_len); | ||
948 | struct ieee80211_bss * | ||
949 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | ||
950 | u8 *ssid, u8 ssid_len); | ||
951 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
952 | struct ieee80211_bss *bss); | ||
931 | 953 | ||
932 | /* interface handling */ | 954 | /* interface handling */ |
933 | void ieee80211_if_setup(struct net_device *dev); | ||
934 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 955 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
935 | struct net_device **new_dev, enum ieee80211_if_types type, | 956 | struct net_device **new_dev, enum nl80211_iftype type, |
936 | struct vif_params *params); | 957 | struct vif_params *params); |
937 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 958 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
938 | enum ieee80211_if_types type); | 959 | enum nl80211_iftype type); |
939 | void ieee80211_if_remove(struct net_device *dev); | 960 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
940 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 961 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
941 | 962 | ||
942 | /* tx handling */ | 963 | /* tx handling */ |
@@ -946,16 +967,52 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); | |||
946 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | 967 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); |
947 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 968 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
948 | 969 | ||
970 | /* HT */ | ||
971 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
972 | struct ieee80211_ht_info *ht_info); | ||
973 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
974 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
975 | struct ieee80211_ht_bss_info *bss_info); | ||
976 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | ||
977 | |||
978 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | ||
979 | u16 tid, u16 initiator, u16 reason); | ||
980 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); | ||
981 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | ||
982 | struct sta_info *sta, | ||
983 | struct ieee80211_mgmt *mgmt, size_t len); | ||
984 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | ||
985 | struct sta_info *sta, | ||
986 | struct ieee80211_mgmt *mgmt, | ||
987 | size_t len); | ||
988 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
989 | struct sta_info *sta, | ||
990 | struct ieee80211_mgmt *mgmt, | ||
991 | size_t len); | ||
992 | |||
993 | /* Spectrum management */ | ||
994 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | ||
995 | struct ieee80211_mgmt *mgmt, | ||
996 | size_t len); | ||
997 | |||
949 | /* utility functions/constants */ | 998 | /* utility functions/constants */ |
950 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 999 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
951 | extern const unsigned char rfc1042_header[6]; | 1000 | extern const unsigned char rfc1042_header[6]; |
952 | extern const unsigned char bridge_tunnel_header[6]; | 1001 | extern const unsigned char bridge_tunnel_header[6]; |
953 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 1002 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
954 | enum ieee80211_if_types type); | 1003 | enum nl80211_iftype type); |
955 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 1004 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
956 | int rate, int erp, int short_preamble); | 1005 | int rate, int erp, int short_preamble); |
957 | void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | 1006 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
958 | struct ieee80211_hdr *hdr); | 1007 | struct ieee80211_hdr *hdr); |
1008 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | ||
1009 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
1010 | int encrypt); | ||
1011 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
1012 | struct ieee802_11_elems *elems); | ||
1013 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | ||
1014 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | ||
1015 | enum ieee80211_band band); | ||
959 | 1016 | ||
960 | #ifdef CONFIG_MAC80211_NOINLINE | 1017 | #ifdef CONFIG_MAC80211_NOINLINE |
961 | #define debug_noinline noinline | 1018 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 610ed1d9893a..8336fee68d3e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Interface handling (except master interface) | ||
3 | * | ||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 4 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 5 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 6 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
@@ -17,7 +19,539 @@ | |||
17 | #include "sta_info.h" | 19 | #include "sta_info.h" |
18 | #include "debugfs_netdev.h" | 20 | #include "debugfs_netdev.h" |
19 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | #include "led.h" | ||
23 | |||
24 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | ||
25 | { | ||
26 | int meshhdrlen; | ||
27 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
28 | |||
29 | meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; | ||
30 | |||
31 | /* FIX: what would be proper limits for MTU? | ||
32 | * This interface uses 802.3 frames. */ | ||
33 | if (new_mtu < 256 || | ||
34 | new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { | ||
35 | return -EINVAL; | ||
36 | } | ||
37 | |||
38 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
39 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | ||
40 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
41 | dev->mtu = new_mtu; | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static inline int identical_mac_addr_allowed(int type1, int type2) | ||
46 | { | ||
47 | return type1 == NL80211_IFTYPE_MONITOR || | ||
48 | type2 == NL80211_IFTYPE_MONITOR || | ||
49 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || | ||
50 | (type1 == NL80211_IFTYPE_WDS && | ||
51 | (type2 == NL80211_IFTYPE_WDS || | ||
52 | type2 == NL80211_IFTYPE_AP)) || | ||
53 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) || | ||
54 | (type1 == NL80211_IFTYPE_AP_VLAN && | ||
55 | (type2 == NL80211_IFTYPE_AP || | ||
56 | type2 == NL80211_IFTYPE_AP_VLAN)); | ||
57 | } | ||
58 | |||
59 | static int ieee80211_open(struct net_device *dev) | ||
60 | { | ||
61 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
62 | struct ieee80211_sub_if_data *nsdata; | ||
63 | struct ieee80211_local *local = sdata->local; | ||
64 | struct sta_info *sta; | ||
65 | struct ieee80211_if_init_conf conf; | ||
66 | u32 changed = 0; | ||
67 | int res; | ||
68 | bool need_hw_reconfig = 0; | ||
69 | u8 null_addr[ETH_ALEN] = {0}; | ||
70 | |||
71 | /* fail early if user set an invalid address */ | ||
72 | if (compare_ether_addr(dev->dev_addr, null_addr) && | ||
73 | !is_valid_ether_addr(dev->dev_addr)) | ||
74 | return -EADDRNOTAVAIL; | ||
75 | |||
76 | /* we hold the RTNL here so can safely walk the list */ | ||
77 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
78 | struct net_device *ndev = nsdata->dev; | ||
79 | |||
80 | if (ndev != dev && netif_running(ndev)) { | ||
81 | /* | ||
82 | * Allow only a single IBSS interface to be up at any | ||
83 | * time. This is restricted because beacon distribution | ||
84 | * cannot work properly if both are in the same IBSS. | ||
85 | * | ||
86 | * To remove this restriction we'd have to disallow them | ||
87 | * from setting the same SSID on different IBSS interfaces | ||
88 | * belonging to the same hardware. Then, however, we're | ||
89 | * faced with having to adopt two different TSF timers... | ||
90 | */ | ||
91 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
92 | nsdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
93 | return -EBUSY; | ||
94 | |||
95 | /* | ||
96 | * The remaining checks are only performed for interfaces | ||
97 | * with the same MAC address. | ||
98 | */ | ||
99 | if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) | ||
100 | continue; | ||
101 | |||
102 | /* | ||
103 | * check whether it may have the same address | ||
104 | */ | ||
105 | if (!identical_mac_addr_allowed(sdata->vif.type, | ||
106 | nsdata->vif.type)) | ||
107 | return -ENOTUNIQ; | ||
108 | |||
109 | /* | ||
110 | * can only add VLANs to enabled APs | ||
111 | */ | ||
112 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | ||
113 | nsdata->vif.type == NL80211_IFTYPE_AP) | ||
114 | sdata->bss = &nsdata->u.ap; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | switch (sdata->vif.type) { | ||
119 | case NL80211_IFTYPE_WDS: | ||
120 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | ||
121 | return -ENOLINK; | ||
122 | break; | ||
123 | case NL80211_IFTYPE_AP_VLAN: | ||
124 | if (!sdata->bss) | ||
125 | return -ENOLINK; | ||
126 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
127 | break; | ||
128 | case NL80211_IFTYPE_AP: | ||
129 | sdata->bss = &sdata->u.ap; | ||
130 | break; | ||
131 | case NL80211_IFTYPE_MESH_POINT: | ||
132 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
133 | break; | ||
134 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
135 | atomic_inc(&local->iff_allmultis); | ||
136 | break; | ||
137 | case NL80211_IFTYPE_STATION: | ||
138 | case NL80211_IFTYPE_MONITOR: | ||
139 | case NL80211_IFTYPE_ADHOC: | ||
140 | /* no special treatment */ | ||
141 | break; | ||
142 | case NL80211_IFTYPE_UNSPECIFIED: | ||
143 | case __NL80211_IFTYPE_AFTER_LAST: | ||
144 | /* cannot happen */ | ||
145 | WARN_ON(1); | ||
146 | break; | ||
147 | } | ||
148 | |||
149 | if (local->open_count == 0) { | ||
150 | res = 0; | ||
151 | if (local->ops->start) | ||
152 | res = local->ops->start(local_to_hw(local)); | ||
153 | if (res) | ||
154 | goto err_del_bss; | ||
155 | need_hw_reconfig = 1; | ||
156 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Check all interfaces and copy the hopefully now-present | ||
161 | * MAC address to those that have the special null one. | ||
162 | */ | ||
163 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
164 | struct net_device *ndev = nsdata->dev; | ||
165 | |||
166 | /* | ||
167 | * No need to check netif_running since we do not allow | ||
168 | * it to start up with this invalid address. | ||
169 | */ | ||
170 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) | ||
171 | memcpy(ndev->dev_addr, | ||
172 | local->hw.wiphy->perm_addr, | ||
173 | ETH_ALEN); | ||
174 | } | ||
175 | |||
176 | if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) | ||
177 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, | ||
178 | ETH_ALEN); | ||
179 | |||
180 | /* | ||
181 | * Validate the MAC address for this device. | ||
182 | */ | ||
183 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
184 | if (!local->open_count && local->ops->stop) | ||
185 | local->ops->stop(local_to_hw(local)); | ||
186 | return -EADDRNOTAVAIL; | ||
187 | } | ||
188 | |||
189 | switch (sdata->vif.type) { | ||
190 | case NL80211_IFTYPE_AP_VLAN: | ||
191 | /* no need to tell driver */ | ||
192 | break; | ||
193 | case NL80211_IFTYPE_MONITOR: | ||
194 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
195 | local->cooked_mntrs++; | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | /* must be before the call to ieee80211_configure_filter */ | ||
200 | local->monitors++; | ||
201 | if (local->monitors == 1) | ||
202 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
203 | |||
204 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
205 | local->fif_fcsfail++; | ||
206 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
207 | local->fif_plcpfail++; | ||
208 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
209 | local->fif_control++; | ||
210 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
211 | local->fif_other_bss++; | ||
212 | |||
213 | netif_addr_lock_bh(local->mdev); | ||
214 | ieee80211_configure_filter(local); | ||
215 | netif_addr_unlock_bh(local->mdev); | ||
216 | break; | ||
217 | case NL80211_IFTYPE_STATION: | ||
218 | case NL80211_IFTYPE_ADHOC: | ||
219 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
220 | /* fall through */ | ||
221 | default: | ||
222 | conf.vif = &sdata->vif; | ||
223 | conf.type = sdata->vif.type; | ||
224 | conf.mac_addr = dev->dev_addr; | ||
225 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
226 | if (res) | ||
227 | goto err_stop; | ||
228 | |||
229 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
230 | ieee80211_start_mesh(sdata); | ||
231 | changed |= ieee80211_reset_erp_info(sdata); | ||
232 | ieee80211_bss_info_change_notify(sdata, changed); | ||
233 | ieee80211_enable_keys(sdata); | ||
234 | |||
235 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
236 | !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) | ||
237 | netif_carrier_off(dev); | ||
238 | else | ||
239 | netif_carrier_on(dev); | ||
240 | } | ||
241 | |||
242 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { | ||
243 | /* Create STA entry for the WDS peer */ | ||
244 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | ||
245 | GFP_KERNEL); | ||
246 | if (!sta) { | ||
247 | res = -ENOMEM; | ||
248 | goto err_del_interface; | ||
249 | } | ||
250 | |||
251 | /* no locking required since STA is not live yet */ | ||
252 | sta->flags |= WLAN_STA_AUTHORIZED; | ||
253 | |||
254 | res = sta_info_insert(sta); | ||
255 | if (res) { | ||
256 | /* STA has been freed */ | ||
257 | goto err_del_interface; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | if (local->open_count == 0) { | ||
262 | res = dev_open(local->mdev); | ||
263 | WARN_ON(res); | ||
264 | if (res) | ||
265 | goto err_del_interface; | ||
266 | tasklet_enable(&local->tx_pending_tasklet); | ||
267 | tasklet_enable(&local->tasklet); | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * set_multicast_list will be invoked by the networking core | ||
272 | * which will check whether any increments here were done in | ||
273 | * error and sync them down to the hardware as filter flags. | ||
274 | */ | ||
275 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
276 | atomic_inc(&local->iff_allmultis); | ||
277 | |||
278 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
279 | atomic_inc(&local->iff_promiscs); | ||
280 | |||
281 | local->open_count++; | ||
282 | if (need_hw_reconfig) { | ||
283 | ieee80211_hw_config(local); | ||
284 | /* | ||
285 | * set default queue parameters so drivers don't | ||
286 | * need to initialise the hardware if the hardware | ||
287 | * doesn't start up with sane defaults | ||
288 | */ | ||
289 | ieee80211_set_wmm_default(sdata); | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * ieee80211_sta_work is disabled while network interface | ||
294 | * is down. Therefore, some configuration changes may not | ||
295 | * yet be effective. Trigger execution of ieee80211_sta_work | ||
296 | * to fix this. | ||
297 | */ | ||
298 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | ||
299 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
300 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
301 | queue_work(local->hw.workqueue, &ifsta->work); | ||
302 | } | ||
303 | |||
304 | netif_tx_start_all_queues(dev); | ||
305 | |||
306 | return 0; | ||
307 | err_del_interface: | ||
308 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
309 | err_stop: | ||
310 | if (!local->open_count && local->ops->stop) | ||
311 | local->ops->stop(local_to_hw(local)); | ||
312 | err_del_bss: | ||
313 | sdata->bss = NULL; | ||
314 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
315 | list_del(&sdata->u.vlan.list); | ||
316 | return res; | ||
317 | } | ||
318 | |||
319 | static int ieee80211_stop(struct net_device *dev) | ||
320 | { | ||
321 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
322 | struct ieee80211_local *local = sdata->local; | ||
323 | struct ieee80211_if_init_conf conf; | ||
324 | struct sta_info *sta; | ||
325 | |||
326 | /* | ||
327 | * Stop TX on this interface first. | ||
328 | */ | ||
329 | netif_tx_stop_all_queues(dev); | ||
330 | |||
331 | /* | ||
332 | * Now delete all active aggregation sessions. | ||
333 | */ | ||
334 | rcu_read_lock(); | ||
335 | |||
336 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
337 | if (sta->sdata == sdata) | ||
338 | ieee80211_sta_tear_down_BA_sessions(sdata, | ||
339 | sta->sta.addr); | ||
340 | } | ||
341 | |||
342 | rcu_read_unlock(); | ||
343 | |||
344 | /* | ||
345 | * Remove all stations associated with this interface. | ||
346 | * | ||
347 | * This must be done before calling ops->remove_interface() | ||
348 | * because otherwise we can later invoke ops->sta_notify() | ||
349 | * whenever the STAs are removed, and that invalidates driver | ||
350 | * assumptions about always getting a vif pointer that is valid | ||
351 | * (because if we remove a STA after ops->remove_interface() | ||
352 | * the driver will have removed the vif info already!) | ||
353 | * | ||
354 | * We could relax this and only unlink the stations from the | ||
355 | * hash table and list but keep them on a per-sdata list that | ||
356 | * will be inserted back again when the interface is brought | ||
357 | * up again, but I don't currently see a use case for that, | ||
358 | * except with WDS which gets a STA entry created when it is | ||
359 | * brought up. | ||
360 | */ | ||
361 | sta_info_flush(local, sdata); | ||
362 | |||
363 | /* | ||
364 | * Don't count this interface for promisc/allmulti while it | ||
365 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
366 | * on the master interface which will sync these down to the | ||
367 | * hardware as filter flags. | ||
368 | */ | ||
369 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
370 | atomic_dec(&local->iff_allmultis); | ||
371 | |||
372 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
373 | atomic_dec(&local->iff_promiscs); | ||
374 | |||
375 | dev_mc_unsync(local->mdev, dev); | ||
376 | |||
377 | /* APs need special treatment */ | ||
378 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
379 | struct ieee80211_sub_if_data *vlan, *tmp; | ||
380 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | ||
381 | |||
382 | /* remove beacon */ | ||
383 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | ||
384 | synchronize_rcu(); | ||
385 | kfree(old_beacon); | ||
386 | |||
387 | /* down all dependent devices, that is VLANs */ | ||
388 | list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, | ||
389 | u.vlan.list) | ||
390 | dev_close(vlan->dev); | ||
391 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | ||
392 | } | ||
393 | |||
394 | local->open_count--; | ||
395 | |||
396 | switch (sdata->vif.type) { | ||
397 | case NL80211_IFTYPE_AP_VLAN: | ||
398 | list_del(&sdata->u.vlan.list); | ||
399 | /* no need to tell driver */ | ||
400 | break; | ||
401 | case NL80211_IFTYPE_MONITOR: | ||
402 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
403 | local->cooked_mntrs--; | ||
404 | break; | ||
405 | } | ||
406 | |||
407 | local->monitors--; | ||
408 | if (local->monitors == 0) | ||
409 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
410 | |||
411 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
412 | local->fif_fcsfail--; | ||
413 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
414 | local->fif_plcpfail--; | ||
415 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
416 | local->fif_control--; | ||
417 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
418 | local->fif_other_bss--; | ||
419 | |||
420 | netif_addr_lock_bh(local->mdev); | ||
421 | ieee80211_configure_filter(local); | ||
422 | netif_addr_unlock_bh(local->mdev); | ||
423 | break; | ||
424 | case NL80211_IFTYPE_STATION: | ||
425 | case NL80211_IFTYPE_ADHOC: | ||
426 | sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; | ||
427 | memset(sdata->u.sta.bssid, 0, ETH_ALEN); | ||
428 | del_timer_sync(&sdata->u.sta.timer); | ||
429 | /* | ||
430 | * If the timer fired while we waited for it, it will have | ||
431 | * requeued the work. Now the work will be running again | ||
432 | * but will not rearm the timer again because it checks | ||
433 | * whether the interface is running, which, at this point, | ||
434 | * it no longer is. | ||
435 | */ | ||
436 | cancel_work_sync(&sdata->u.sta.work); | ||
437 | /* | ||
438 | * When we get here, the interface is marked down. | ||
439 | * Call synchronize_rcu() to wait for the RX path | ||
440 | * should it be using the interface and enqueuing | ||
441 | * frames at this very time on another CPU. | ||
442 | */ | ||
443 | synchronize_rcu(); | ||
444 | skb_queue_purge(&sdata->u.sta.skb_queue); | ||
445 | |||
446 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | ||
447 | kfree(sdata->u.sta.extra_ie); | ||
448 | sdata->u.sta.extra_ie = NULL; | ||
449 | sdata->u.sta.extra_ie_len = 0; | ||
450 | /* fall through */ | ||
451 | case NL80211_IFTYPE_MESH_POINT: | ||
452 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
453 | /* allmulti is always set on mesh ifaces */ | ||
454 | atomic_dec(&local->iff_allmultis); | ||
455 | ieee80211_stop_mesh(sdata); | ||
456 | } | ||
457 | /* fall through */ | ||
458 | default: | ||
459 | if (local->scan_sdata == sdata) { | ||
460 | if (!local->ops->hw_scan) | ||
461 | cancel_delayed_work_sync(&local->scan_work); | ||
462 | /* | ||
463 | * The software scan can no longer run now, so we can | ||
464 | * clear out the scan_sdata reference. However, the | ||
465 | * hardware scan may still be running. The complete | ||
466 | * function must be prepared to handle a NULL value. | ||
467 | */ | ||
468 | local->scan_sdata = NULL; | ||
469 | /* | ||
470 | * The memory barrier guarantees that another CPU | ||
471 | * that is hardware-scanning will now see the fact | ||
472 | * that this interface is gone. | ||
473 | */ | ||
474 | smp_mb(); | ||
475 | /* | ||
476 | * If software scanning, complete the scan but since | ||
477 | * the scan_sdata is NULL already don't send out a | ||
478 | * scan event to userspace -- the scan is incomplete. | ||
479 | */ | ||
480 | if (local->sw_scanning) | ||
481 | ieee80211_scan_completed(&local->hw); | ||
482 | } | ||
483 | |||
484 | conf.vif = &sdata->vif; | ||
485 | conf.type = sdata->vif.type; | ||
486 | conf.mac_addr = dev->dev_addr; | ||
487 | /* disable all keys for as long as this netdev is down */ | ||
488 | ieee80211_disable_keys(sdata); | ||
489 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
490 | } | ||
491 | |||
492 | sdata->bss = NULL; | ||
493 | |||
494 | if (local->open_count == 0) { | ||
495 | if (netif_running(local->mdev)) | ||
496 | dev_close(local->mdev); | ||
497 | |||
498 | if (local->ops->stop) | ||
499 | local->ops->stop(local_to_hw(local)); | ||
500 | |||
501 | ieee80211_led_radio(local, 0); | ||
502 | |||
503 | flush_workqueue(local->hw.workqueue); | ||
504 | |||
505 | tasklet_disable(&local->tx_pending_tasklet); | ||
506 | tasklet_disable(&local->tasklet); | ||
507 | } | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static void ieee80211_set_multicast_list(struct net_device *dev) | ||
513 | { | ||
514 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
515 | struct ieee80211_local *local = sdata->local; | ||
516 | int allmulti, promisc, sdata_allmulti, sdata_promisc; | ||
517 | |||
518 | allmulti = !!(dev->flags & IFF_ALLMULTI); | ||
519 | promisc = !!(dev->flags & IFF_PROMISC); | ||
520 | sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); | ||
521 | sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); | ||
522 | |||
523 | if (allmulti != sdata_allmulti) { | ||
524 | if (dev->flags & IFF_ALLMULTI) | ||
525 | atomic_inc(&local->iff_allmultis); | ||
526 | else | ||
527 | atomic_dec(&local->iff_allmultis); | ||
528 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | ||
529 | } | ||
530 | |||
531 | if (promisc != sdata_promisc) { | ||
532 | if (dev->flags & IFF_PROMISC) | ||
533 | atomic_inc(&local->iff_promiscs); | ||
534 | else | ||
535 | atomic_dec(&local->iff_promiscs); | ||
536 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | ||
537 | } | ||
538 | |||
539 | dev_mc_sync(local->mdev, dev); | ||
540 | } | ||
20 | 541 | ||
542 | static void ieee80211_if_setup(struct net_device *dev) | ||
543 | { | ||
544 | ether_setup(dev); | ||
545 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
546 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
547 | dev->set_multicast_list = ieee80211_set_multicast_list; | ||
548 | dev->change_mtu = ieee80211_change_mtu; | ||
549 | dev->open = ieee80211_open; | ||
550 | dev->stop = ieee80211_stop; | ||
551 | dev->destructor = free_netdev; | ||
552 | /* we will validate the address ourselves in ->open */ | ||
553 | dev->validate_addr = NULL; | ||
554 | } | ||
21 | /* | 555 | /* |
22 | * Called when the netdev is removed or, by the code below, before | 556 | * Called when the netdev is removed or, by the code below, before |
23 | * the interface type changes. | 557 | * the interface type changes. |
@@ -31,17 +565,17 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
31 | int flushed; | 565 | int flushed; |
32 | int i; | 566 | int i; |
33 | 567 | ||
34 | ieee80211_debugfs_remove_netdev(sdata); | ||
35 | |||
36 | /* free extra data */ | 568 | /* free extra data */ |
37 | ieee80211_free_keys(sdata); | 569 | ieee80211_free_keys(sdata); |
38 | 570 | ||
571 | ieee80211_debugfs_remove_netdev(sdata); | ||
572 | |||
39 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 573 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
40 | __skb_queue_purge(&sdata->fragments[i].skb_list); | 574 | __skb_queue_purge(&sdata->fragments[i].skb_list); |
41 | sdata->fragment_next = 0; | 575 | sdata->fragment_next = 0; |
42 | 576 | ||
43 | switch (sdata->vif.type) { | 577 | switch (sdata->vif.type) { |
44 | case IEEE80211_IF_TYPE_AP: | 578 | case NL80211_IFTYPE_AP: |
45 | beacon = sdata->u.ap.beacon; | 579 | beacon = sdata->u.ap.beacon; |
46 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 580 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
47 | synchronize_rcu(); | 581 | synchronize_rcu(); |
@@ -53,23 +587,23 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
53 | } | 587 | } |
54 | 588 | ||
55 | break; | 589 | break; |
56 | case IEEE80211_IF_TYPE_MESH_POINT: | 590 | case NL80211_IFTYPE_MESH_POINT: |
57 | /* Allow compiler to elide mesh_rmc_free call. */ | ||
58 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 591 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
59 | mesh_rmc_free(dev); | 592 | mesh_rmc_free(sdata); |
60 | /* fall through */ | 593 | break; |
61 | case IEEE80211_IF_TYPE_STA: | 594 | case NL80211_IFTYPE_STATION: |
62 | case IEEE80211_IF_TYPE_IBSS: | 595 | case NL80211_IFTYPE_ADHOC: |
63 | kfree(sdata->u.sta.extra_ie); | 596 | kfree(sdata->u.sta.extra_ie); |
64 | kfree(sdata->u.sta.assocreq_ies); | 597 | kfree(sdata->u.sta.assocreq_ies); |
65 | kfree(sdata->u.sta.assocresp_ies); | 598 | kfree(sdata->u.sta.assocresp_ies); |
66 | kfree_skb(sdata->u.sta.probe_resp); | 599 | kfree_skb(sdata->u.sta.probe_resp); |
67 | break; | 600 | break; |
68 | case IEEE80211_IF_TYPE_WDS: | 601 | case NL80211_IFTYPE_WDS: |
69 | case IEEE80211_IF_TYPE_VLAN: | 602 | case NL80211_IFTYPE_AP_VLAN: |
70 | case IEEE80211_IF_TYPE_MNTR: | 603 | case NL80211_IFTYPE_MONITOR: |
71 | break; | 604 | break; |
72 | case IEEE80211_IF_TYPE_INVALID: | 605 | case NL80211_IFTYPE_UNSPECIFIED: |
606 | case __NL80211_IFTYPE_AFTER_LAST: | ||
73 | BUG(); | 607 | BUG(); |
74 | break; | 608 | break; |
75 | } | 609 | } |
@@ -82,55 +616,43 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
82 | * Helper function to initialise an interface to a specific type. | 616 | * Helper function to initialise an interface to a specific type. |
83 | */ | 617 | */ |
84 | static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | 618 | static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, |
85 | enum ieee80211_if_types type) | 619 | enum nl80211_iftype type) |
86 | { | 620 | { |
87 | struct ieee80211_if_sta *ifsta; | ||
88 | |||
89 | /* clear type-dependent union */ | 621 | /* clear type-dependent union */ |
90 | memset(&sdata->u, 0, sizeof(sdata->u)); | 622 | memset(&sdata->u, 0, sizeof(sdata->u)); |
91 | 623 | ||
92 | /* and set some type-dependent values */ | 624 | /* and set some type-dependent values */ |
93 | sdata->vif.type = type; | 625 | sdata->vif.type = type; |
626 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
627 | sdata->wdev.iftype = type; | ||
94 | 628 | ||
95 | /* only monitor differs */ | 629 | /* only monitor differs */ |
96 | sdata->dev->type = ARPHRD_ETHER; | 630 | sdata->dev->type = ARPHRD_ETHER; |
97 | 631 | ||
98 | switch (type) { | 632 | switch (type) { |
99 | case IEEE80211_IF_TYPE_AP: | 633 | case NL80211_IFTYPE_AP: |
100 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 634 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
101 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 635 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
102 | break; | 636 | break; |
103 | case IEEE80211_IF_TYPE_MESH_POINT: | 637 | case NL80211_IFTYPE_STATION: |
104 | case IEEE80211_IF_TYPE_STA: | 638 | case NL80211_IFTYPE_ADHOC: |
105 | case IEEE80211_IF_TYPE_IBSS: | 639 | ieee80211_sta_setup_sdata(sdata); |
106 | ifsta = &sdata->u.sta; | 640 | break; |
107 | INIT_WORK(&ifsta->work, ieee80211_sta_work); | 641 | case NL80211_IFTYPE_MESH_POINT: |
108 | setup_timer(&ifsta->timer, ieee80211_sta_timer, | ||
109 | (unsigned long) sdata); | ||
110 | skb_queue_head_init(&ifsta->skb_queue); | ||
111 | |||
112 | ifsta->capab = WLAN_CAPABILITY_ESS; | ||
113 | ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | | ||
114 | IEEE80211_AUTH_ALG_SHARED_KEY; | ||
115 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | ||
116 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
117 | IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
118 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | ||
119 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | ||
120 | |||
121 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 642 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
122 | ieee80211_mesh_init_sdata(sdata); | 643 | ieee80211_mesh_init_sdata(sdata); |
123 | break; | 644 | break; |
124 | case IEEE80211_IF_TYPE_MNTR: | 645 | case NL80211_IFTYPE_MONITOR: |
125 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; | 646 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
126 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; | 647 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; |
127 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | | 648 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | |
128 | MONITOR_FLAG_OTHER_BSS; | 649 | MONITOR_FLAG_OTHER_BSS; |
129 | break; | 650 | break; |
130 | case IEEE80211_IF_TYPE_WDS: | 651 | case NL80211_IFTYPE_WDS: |
131 | case IEEE80211_IF_TYPE_VLAN: | 652 | case NL80211_IFTYPE_AP_VLAN: |
132 | break; | 653 | break; |
133 | case IEEE80211_IF_TYPE_INVALID: | 654 | case NL80211_IFTYPE_UNSPECIFIED: |
655 | case __NL80211_IFTYPE_AFTER_LAST: | ||
134 | BUG(); | 656 | BUG(); |
135 | break; | 657 | break; |
136 | } | 658 | } |
@@ -139,7 +661,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
139 | } | 661 | } |
140 | 662 | ||
141 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 663 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
142 | enum ieee80211_if_types type) | 664 | enum nl80211_iftype type) |
143 | { | 665 | { |
144 | ASSERT_RTNL(); | 666 | ASSERT_RTNL(); |
145 | 667 | ||
@@ -160,14 +682,16 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
160 | ieee80211_setup_sdata(sdata, type); | 682 | ieee80211_setup_sdata(sdata, type); |
161 | 683 | ||
162 | /* reset some values that shouldn't be kept across type changes */ | 684 | /* reset some values that shouldn't be kept across type changes */ |
163 | sdata->basic_rates = 0; | 685 | sdata->bss_conf.basic_rates = |
686 | ieee80211_mandatory_rates(sdata->local, | ||
687 | sdata->local->hw.conf.channel->band); | ||
164 | sdata->drop_unencrypted = 0; | 688 | sdata->drop_unencrypted = 0; |
165 | 689 | ||
166 | return 0; | 690 | return 0; |
167 | } | 691 | } |
168 | 692 | ||
169 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 693 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
170 | struct net_device **new_dev, enum ieee80211_if_types type, | 694 | struct net_device **new_dev, enum nl80211_iftype type, |
171 | struct vif_params *params) | 695 | struct vif_params *params) |
172 | { | 696 | { |
173 | struct net_device *ndev; | 697 | struct net_device *ndev; |
@@ -225,9 +749,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
225 | 749 | ||
226 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 750 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
227 | params && params->mesh_id_len) | 751 | params && params->mesh_id_len) |
228 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 752 | ieee80211_sdata_set_mesh_id(sdata, |
229 | params->mesh_id_len, | 753 | params->mesh_id_len, |
230 | params->mesh_id); | 754 | params->mesh_id); |
231 | 755 | ||
232 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 756 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
233 | 757 | ||
@@ -241,15 +765,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
241 | return ret; | 765 | return ret; |
242 | } | 766 | } |
243 | 767 | ||
244 | void ieee80211_if_remove(struct net_device *dev) | 768 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) |
245 | { | 769 | { |
246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
247 | |||
248 | ASSERT_RTNL(); | 770 | ASSERT_RTNL(); |
249 | 771 | ||
250 | list_del_rcu(&sdata->list); | 772 | list_del_rcu(&sdata->list); |
251 | synchronize_rcu(); | 773 | synchronize_rcu(); |
252 | unregister_netdevice(dev); | 774 | unregister_netdevice(sdata->dev); |
253 | } | 775 | } |
254 | 776 | ||
255 | /* | 777 | /* |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6597c779e35a..a5b06fe71980 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -118,12 +118,12 @@ static const u8 *get_mac_for_key(struct ieee80211_key *key) | |||
118 | * address to indicate a transmit-only key. | 118 | * address to indicate a transmit-only key. |
119 | */ | 119 | */ |
120 | if (key->conf.alg != ALG_WEP && | 120 | if (key->conf.alg != ALG_WEP && |
121 | (key->sdata->vif.type == IEEE80211_IF_TYPE_AP || | 121 | (key->sdata->vif.type == NL80211_IFTYPE_AP || |
122 | key->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) | 122 | key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) |
123 | addr = zero_addr; | 123 | addr = zero_addr; |
124 | 124 | ||
125 | if (key->sta) | 125 | if (key->sta) |
126 | addr = key->sta->addr; | 126 | addr = key->sta->sta.addr; |
127 | 127 | ||
128 | return addr; | 128 | return addr; |
129 | } | 129 | } |
@@ -281,6 +281,20 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
281 | key->conf.alg = alg; | 281 | key->conf.alg = alg; |
282 | key->conf.keyidx = idx; | 282 | key->conf.keyidx = idx; |
283 | key->conf.keylen = key_len; | 283 | key->conf.keylen = key_len; |
284 | switch (alg) { | ||
285 | case ALG_WEP: | ||
286 | key->conf.iv_len = WEP_IV_LEN; | ||
287 | key->conf.icv_len = WEP_ICV_LEN; | ||
288 | break; | ||
289 | case ALG_TKIP: | ||
290 | key->conf.iv_len = TKIP_IV_LEN; | ||
291 | key->conf.icv_len = TKIP_ICV_LEN; | ||
292 | break; | ||
293 | case ALG_CCMP: | ||
294 | key->conf.iv_len = CCMP_HDR_LEN; | ||
295 | key->conf.icv_len = CCMP_MIC_LEN; | ||
296 | break; | ||
297 | } | ||
284 | memcpy(key->conf.key, key_data, key_len); | 298 | memcpy(key->conf.key, key_data, key_len); |
285 | INIT_LIST_HEAD(&key->list); | 299 | INIT_LIST_HEAD(&key->list); |
286 | INIT_LIST_HEAD(&key->todo); | 300 | INIT_LIST_HEAD(&key->todo); |
@@ -331,7 +345,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
331 | */ | 345 | */ |
332 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | 346 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
333 | } else { | 347 | } else { |
334 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 348 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
335 | struct sta_info *ap; | 349 | struct sta_info *ap; |
336 | 350 | ||
337 | /* | 351 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index aa5a191598c9..ae62ad40ad63 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -45,16 +45,9 @@ struct ieee80211_tx_status_rtap_hdr { | |||
45 | u8 data_retries; | 45 | u8 data_retries; |
46 | } __attribute__ ((packed)); | 46 | } __attribute__ ((packed)); |
47 | 47 | ||
48 | /* common interface routines */ | ||
49 | |||
50 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
51 | { | ||
52 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
53 | return ETH_ALEN; | ||
54 | } | ||
55 | 48 | ||
56 | /* must be called under mdev tx lock */ | 49 | /* must be called under mdev tx lock */ |
57 | static void ieee80211_configure_filter(struct ieee80211_local *local) | 50 | void ieee80211_configure_filter(struct ieee80211_local *local) |
58 | { | 51 | { |
59 | unsigned int changed_flags; | 52 | unsigned int changed_flags; |
60 | unsigned int new_flags = 0; | 53 | unsigned int new_flags = 0; |
@@ -97,9 +90,24 @@ static void ieee80211_configure_filter(struct ieee80211_local *local) | |||
97 | 90 | ||
98 | /* master interface */ | 91 | /* master interface */ |
99 | 92 | ||
93 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
94 | { | ||
95 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
96 | return ETH_ALEN; | ||
97 | } | ||
98 | |||
99 | static const struct header_ops ieee80211_header_ops = { | ||
100 | .create = eth_header, | ||
101 | .parse = header_parse_80211, | ||
102 | .rebuild = eth_rebuild_header, | ||
103 | .cache = eth_header_cache, | ||
104 | .cache_update = eth_header_cache_update, | ||
105 | }; | ||
106 | |||
100 | static int ieee80211_master_open(struct net_device *dev) | 107 | static int ieee80211_master_open(struct net_device *dev) |
101 | { | 108 | { |
102 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 109 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
110 | struct ieee80211_local *local = mpriv->local; | ||
103 | struct ieee80211_sub_if_data *sdata; | 111 | struct ieee80211_sub_if_data *sdata; |
104 | int res = -EOPNOTSUPP; | 112 | int res = -EOPNOTSUPP; |
105 | 113 | ||
@@ -121,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) | |||
121 | 129 | ||
122 | static int ieee80211_master_stop(struct net_device *dev) | 130 | static int ieee80211_master_stop(struct net_device *dev) |
123 | { | 131 | { |
124 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 132 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
133 | struct ieee80211_local *local = mpriv->local; | ||
125 | struct ieee80211_sub_if_data *sdata; | 134 | struct ieee80211_sub_if_data *sdata; |
126 | 135 | ||
127 | /* we hold the RTNL here so can safely walk the list */ | 136 | /* we hold the RTNL here so can safely walk the list */ |
@@ -134,849 +143,12 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
134 | 143 | ||
135 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | 144 | static void ieee80211_master_set_multicast_list(struct net_device *dev) |
136 | { | 145 | { |
137 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 146 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
147 | struct ieee80211_local *local = mpriv->local; | ||
138 | 148 | ||
139 | ieee80211_configure_filter(local); | 149 | ieee80211_configure_filter(local); |
140 | } | 150 | } |
141 | 151 | ||
142 | /* regular interfaces */ | ||
143 | |||
144 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | ||
145 | { | ||
146 | int meshhdrlen; | ||
147 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
148 | |||
149 | meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0; | ||
150 | |||
151 | /* FIX: what would be proper limits for MTU? | ||
152 | * This interface uses 802.3 frames. */ | ||
153 | if (new_mtu < 256 || | ||
154 | new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | |||
158 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
159 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | ||
160 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
161 | dev->mtu = new_mtu; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static inline int identical_mac_addr_allowed(int type1, int type2) | ||
166 | { | ||
167 | return (type1 == IEEE80211_IF_TYPE_MNTR || | ||
168 | type2 == IEEE80211_IF_TYPE_MNTR || | ||
169 | (type1 == IEEE80211_IF_TYPE_AP && | ||
170 | type2 == IEEE80211_IF_TYPE_WDS) || | ||
171 | (type1 == IEEE80211_IF_TYPE_WDS && | ||
172 | (type2 == IEEE80211_IF_TYPE_WDS || | ||
173 | type2 == IEEE80211_IF_TYPE_AP)) || | ||
174 | (type1 == IEEE80211_IF_TYPE_AP && | ||
175 | type2 == IEEE80211_IF_TYPE_VLAN) || | ||
176 | (type1 == IEEE80211_IF_TYPE_VLAN && | ||
177 | (type2 == IEEE80211_IF_TYPE_AP || | ||
178 | type2 == IEEE80211_IF_TYPE_VLAN))); | ||
179 | } | ||
180 | |||
181 | static int ieee80211_open(struct net_device *dev) | ||
182 | { | ||
183 | struct ieee80211_sub_if_data *sdata, *nsdata; | ||
184 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
185 | struct sta_info *sta; | ||
186 | struct ieee80211_if_init_conf conf; | ||
187 | u32 changed = 0; | ||
188 | int res; | ||
189 | bool need_hw_reconfig = 0; | ||
190 | |||
191 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
192 | |||
193 | /* we hold the RTNL here so can safely walk the list */ | ||
194 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
195 | struct net_device *ndev = nsdata->dev; | ||
196 | |||
197 | if (ndev != dev && netif_running(ndev)) { | ||
198 | /* | ||
199 | * Allow only a single IBSS interface to be up at any | ||
200 | * time. This is restricted because beacon distribution | ||
201 | * cannot work properly if both are in the same IBSS. | ||
202 | * | ||
203 | * To remove this restriction we'd have to disallow them | ||
204 | * from setting the same SSID on different IBSS interfaces | ||
205 | * belonging to the same hardware. Then, however, we're | ||
206 | * faced with having to adopt two different TSF timers... | ||
207 | */ | ||
208 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | ||
209 | nsdata->vif.type == IEEE80211_IF_TYPE_IBSS) | ||
210 | return -EBUSY; | ||
211 | |||
212 | /* | ||
213 | * The remaining checks are only performed for interfaces | ||
214 | * with the same MAC address. | ||
215 | */ | ||
216 | if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) | ||
217 | continue; | ||
218 | |||
219 | /* | ||
220 | * check whether it may have the same address | ||
221 | */ | ||
222 | if (!identical_mac_addr_allowed(sdata->vif.type, | ||
223 | nsdata->vif.type)) | ||
224 | return -ENOTUNIQ; | ||
225 | |||
226 | /* | ||
227 | * can only add VLANs to enabled APs | ||
228 | */ | ||
229 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && | ||
230 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) | ||
231 | sdata->bss = &nsdata->u.ap; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | switch (sdata->vif.type) { | ||
236 | case IEEE80211_IF_TYPE_WDS: | ||
237 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | ||
238 | return -ENOLINK; | ||
239 | break; | ||
240 | case IEEE80211_IF_TYPE_VLAN: | ||
241 | if (!sdata->bss) | ||
242 | return -ENOLINK; | ||
243 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
244 | break; | ||
245 | case IEEE80211_IF_TYPE_AP: | ||
246 | sdata->bss = &sdata->u.ap; | ||
247 | break; | ||
248 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
249 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
250 | atomic_inc(&local->iff_allmultis); | ||
251 | break; | ||
252 | case IEEE80211_IF_TYPE_STA: | ||
253 | case IEEE80211_IF_TYPE_MNTR: | ||
254 | case IEEE80211_IF_TYPE_IBSS: | ||
255 | /* no special treatment */ | ||
256 | break; | ||
257 | case IEEE80211_IF_TYPE_INVALID: | ||
258 | /* cannot happen */ | ||
259 | WARN_ON(1); | ||
260 | break; | ||
261 | } | ||
262 | |||
263 | if (local->open_count == 0) { | ||
264 | res = 0; | ||
265 | if (local->ops->start) | ||
266 | res = local->ops->start(local_to_hw(local)); | ||
267 | if (res) | ||
268 | goto err_del_bss; | ||
269 | need_hw_reconfig = 1; | ||
270 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | ||
271 | } | ||
272 | |||
273 | switch (sdata->vif.type) { | ||
274 | case IEEE80211_IF_TYPE_VLAN: | ||
275 | /* no need to tell driver */ | ||
276 | break; | ||
277 | case IEEE80211_IF_TYPE_MNTR: | ||
278 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
279 | local->cooked_mntrs++; | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | /* must be before the call to ieee80211_configure_filter */ | ||
284 | local->monitors++; | ||
285 | if (local->monitors == 1) | ||
286 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
287 | |||
288 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
289 | local->fif_fcsfail++; | ||
290 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
291 | local->fif_plcpfail++; | ||
292 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
293 | local->fif_control++; | ||
294 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
295 | local->fif_other_bss++; | ||
296 | |||
297 | netif_addr_lock_bh(local->mdev); | ||
298 | ieee80211_configure_filter(local); | ||
299 | netif_addr_unlock_bh(local->mdev); | ||
300 | break; | ||
301 | case IEEE80211_IF_TYPE_STA: | ||
302 | case IEEE80211_IF_TYPE_IBSS: | ||
303 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
304 | /* fall through */ | ||
305 | default: | ||
306 | conf.vif = &sdata->vif; | ||
307 | conf.type = sdata->vif.type; | ||
308 | conf.mac_addr = dev->dev_addr; | ||
309 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
310 | if (res) | ||
311 | goto err_stop; | ||
312 | |||
313 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
314 | ieee80211_start_mesh(sdata->dev); | ||
315 | changed |= ieee80211_reset_erp_info(dev); | ||
316 | ieee80211_bss_info_change_notify(sdata, changed); | ||
317 | ieee80211_enable_keys(sdata); | ||
318 | |||
319 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | ||
320 | !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) | ||
321 | netif_carrier_off(dev); | ||
322 | else | ||
323 | netif_carrier_on(dev); | ||
324 | } | ||
325 | |||
326 | if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { | ||
327 | /* Create STA entry for the WDS peer */ | ||
328 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | ||
329 | GFP_KERNEL); | ||
330 | if (!sta) { | ||
331 | res = -ENOMEM; | ||
332 | goto err_del_interface; | ||
333 | } | ||
334 | |||
335 | /* no locking required since STA is not live yet */ | ||
336 | sta->flags |= WLAN_STA_AUTHORIZED; | ||
337 | |||
338 | res = sta_info_insert(sta); | ||
339 | if (res) { | ||
340 | /* STA has been freed */ | ||
341 | goto err_del_interface; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | if (local->open_count == 0) { | ||
346 | res = dev_open(local->mdev); | ||
347 | WARN_ON(res); | ||
348 | if (res) | ||
349 | goto err_del_interface; | ||
350 | tasklet_enable(&local->tx_pending_tasklet); | ||
351 | tasklet_enable(&local->tasklet); | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * set_multicast_list will be invoked by the networking core | ||
356 | * which will check whether any increments here were done in | ||
357 | * error and sync them down to the hardware as filter flags. | ||
358 | */ | ||
359 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
360 | atomic_inc(&local->iff_allmultis); | ||
361 | |||
362 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
363 | atomic_inc(&local->iff_promiscs); | ||
364 | |||
365 | local->open_count++; | ||
366 | if (need_hw_reconfig) | ||
367 | ieee80211_hw_config(local); | ||
368 | |||
369 | /* | ||
370 | * ieee80211_sta_work is disabled while network interface | ||
371 | * is down. Therefore, some configuration changes may not | ||
372 | * yet be effective. Trigger execution of ieee80211_sta_work | ||
373 | * to fix this. | ||
374 | */ | ||
375 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
376 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
377 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
378 | queue_work(local->hw.workqueue, &ifsta->work); | ||
379 | } | ||
380 | |||
381 | netif_tx_start_all_queues(dev); | ||
382 | |||
383 | return 0; | ||
384 | err_del_interface: | ||
385 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
386 | err_stop: | ||
387 | if (!local->open_count && local->ops->stop) | ||
388 | local->ops->stop(local_to_hw(local)); | ||
389 | err_del_bss: | ||
390 | sdata->bss = NULL; | ||
391 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | ||
392 | list_del(&sdata->u.vlan.list); | ||
393 | return res; | ||
394 | } | ||
395 | |||
396 | static int ieee80211_stop(struct net_device *dev) | ||
397 | { | ||
398 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
399 | struct ieee80211_local *local = sdata->local; | ||
400 | struct ieee80211_if_init_conf conf; | ||
401 | struct sta_info *sta; | ||
402 | |||
403 | /* | ||
404 | * Stop TX on this interface first. | ||
405 | */ | ||
406 | netif_tx_stop_all_queues(dev); | ||
407 | |||
408 | /* | ||
409 | * Now delete all active aggregation sessions. | ||
410 | */ | ||
411 | rcu_read_lock(); | ||
412 | |||
413 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
414 | if (sta->sdata == sdata) | ||
415 | ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); | ||
416 | } | ||
417 | |||
418 | rcu_read_unlock(); | ||
419 | |||
420 | /* | ||
421 | * Remove all stations associated with this interface. | ||
422 | * | ||
423 | * This must be done before calling ops->remove_interface() | ||
424 | * because otherwise we can later invoke ops->sta_notify() | ||
425 | * whenever the STAs are removed, and that invalidates driver | ||
426 | * assumptions about always getting a vif pointer that is valid | ||
427 | * (because if we remove a STA after ops->remove_interface() | ||
428 | * the driver will have removed the vif info already!) | ||
429 | * | ||
430 | * We could relax this and only unlink the stations from the | ||
431 | * hash table and list but keep them on a per-sdata list that | ||
432 | * will be inserted back again when the interface is brought | ||
433 | * up again, but I don't currently see a use case for that, | ||
434 | * except with WDS which gets a STA entry created when it is | ||
435 | * brought up. | ||
436 | */ | ||
437 | sta_info_flush(local, sdata); | ||
438 | |||
439 | /* | ||
440 | * Don't count this interface for promisc/allmulti while it | ||
441 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
442 | * on the master interface which will sync these down to the | ||
443 | * hardware as filter flags. | ||
444 | */ | ||
445 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
446 | atomic_dec(&local->iff_allmultis); | ||
447 | |||
448 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
449 | atomic_dec(&local->iff_promiscs); | ||
450 | |||
451 | dev_mc_unsync(local->mdev, dev); | ||
452 | |||
453 | /* APs need special treatment */ | ||
454 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | ||
455 | struct ieee80211_sub_if_data *vlan, *tmp; | ||
456 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | ||
457 | |||
458 | /* remove beacon */ | ||
459 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | ||
460 | synchronize_rcu(); | ||
461 | kfree(old_beacon); | ||
462 | |||
463 | /* down all dependent devices, that is VLANs */ | ||
464 | list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, | ||
465 | u.vlan.list) | ||
466 | dev_close(vlan->dev); | ||
467 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | ||
468 | } | ||
469 | |||
470 | local->open_count--; | ||
471 | |||
472 | switch (sdata->vif.type) { | ||
473 | case IEEE80211_IF_TYPE_VLAN: | ||
474 | list_del(&sdata->u.vlan.list); | ||
475 | /* no need to tell driver */ | ||
476 | break; | ||
477 | case IEEE80211_IF_TYPE_MNTR: | ||
478 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
479 | local->cooked_mntrs--; | ||
480 | break; | ||
481 | } | ||
482 | |||
483 | local->monitors--; | ||
484 | if (local->monitors == 0) | ||
485 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
486 | |||
487 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
488 | local->fif_fcsfail--; | ||
489 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
490 | local->fif_plcpfail--; | ||
491 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
492 | local->fif_control--; | ||
493 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
494 | local->fif_other_bss--; | ||
495 | |||
496 | netif_addr_lock_bh(local->mdev); | ||
497 | ieee80211_configure_filter(local); | ||
498 | netif_addr_unlock_bh(local->mdev); | ||
499 | break; | ||
500 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
501 | /* allmulti is always set on mesh ifaces */ | ||
502 | atomic_dec(&local->iff_allmultis); | ||
503 | /* fall through */ | ||
504 | case IEEE80211_IF_TYPE_STA: | ||
505 | case IEEE80211_IF_TYPE_IBSS: | ||
506 | sdata->u.sta.state = IEEE80211_DISABLED; | ||
507 | memset(sdata->u.sta.bssid, 0, ETH_ALEN); | ||
508 | del_timer_sync(&sdata->u.sta.timer); | ||
509 | /* | ||
510 | * When we get here, the interface is marked down. | ||
511 | * Call synchronize_rcu() to wait for the RX path | ||
512 | * should it be using the interface and enqueuing | ||
513 | * frames at this very time on another CPU. | ||
514 | */ | ||
515 | synchronize_rcu(); | ||
516 | skb_queue_purge(&sdata->u.sta.skb_queue); | ||
517 | |||
518 | if (local->scan_dev == sdata->dev) { | ||
519 | if (!local->ops->hw_scan) { | ||
520 | local->sta_sw_scanning = 0; | ||
521 | cancel_delayed_work(&local->scan_work); | ||
522 | } else | ||
523 | local->sta_hw_scanning = 0; | ||
524 | } | ||
525 | |||
526 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | ||
527 | kfree(sdata->u.sta.extra_ie); | ||
528 | sdata->u.sta.extra_ie = NULL; | ||
529 | sdata->u.sta.extra_ie_len = 0; | ||
530 | /* fall through */ | ||
531 | default: | ||
532 | conf.vif = &sdata->vif; | ||
533 | conf.type = sdata->vif.type; | ||
534 | conf.mac_addr = dev->dev_addr; | ||
535 | /* disable all keys for as long as this netdev is down */ | ||
536 | ieee80211_disable_keys(sdata); | ||
537 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
538 | } | ||
539 | |||
540 | sdata->bss = NULL; | ||
541 | |||
542 | if (local->open_count == 0) { | ||
543 | if (netif_running(local->mdev)) | ||
544 | dev_close(local->mdev); | ||
545 | |||
546 | if (local->ops->stop) | ||
547 | local->ops->stop(local_to_hw(local)); | ||
548 | |||
549 | ieee80211_led_radio(local, 0); | ||
550 | |||
551 | flush_workqueue(local->hw.workqueue); | ||
552 | |||
553 | tasklet_disable(&local->tx_pending_tasklet); | ||
554 | tasklet_disable(&local->tasklet); | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
561 | { | ||
562 | struct ieee80211_local *local = hw_to_local(hw); | ||
563 | struct sta_info *sta; | ||
564 | struct ieee80211_sub_if_data *sdata; | ||
565 | u16 start_seq_num = 0; | ||
566 | u8 *state; | ||
567 | int ret; | ||
568 | DECLARE_MAC_BUF(mac); | ||
569 | |||
570 | if (tid >= STA_TID_NUM) | ||
571 | return -EINVAL; | ||
572 | |||
573 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
574 | printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", | ||
575 | print_mac(mac, ra), tid); | ||
576 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
577 | |||
578 | rcu_read_lock(); | ||
579 | |||
580 | sta = sta_info_get(local, ra); | ||
581 | if (!sta) { | ||
582 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
583 | printk(KERN_DEBUG "Could not find the station\n"); | ||
584 | #endif | ||
585 | ret = -ENOENT; | ||
586 | goto exit; | ||
587 | } | ||
588 | |||
589 | spin_lock_bh(&sta->lock); | ||
590 | |||
591 | /* we have tried too many times, receiver does not want A-MPDU */ | ||
592 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | ||
593 | ret = -EBUSY; | ||
594 | goto err_unlock_sta; | ||
595 | } | ||
596 | |||
597 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
598 | /* check if the TID is not in aggregation flow already */ | ||
599 | if (*state != HT_AGG_STATE_IDLE) { | ||
600 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
601 | printk(KERN_DEBUG "BA request denied - session is not " | ||
602 | "idle on tid %u\n", tid); | ||
603 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
604 | ret = -EAGAIN; | ||
605 | goto err_unlock_sta; | ||
606 | } | ||
607 | |||
608 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
609 | sta->ampdu_mlme.tid_tx[tid] = | ||
610 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
611 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
612 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
613 | if (net_ratelimit()) | ||
614 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
615 | tid); | ||
616 | #endif | ||
617 | ret = -ENOMEM; | ||
618 | goto err_unlock_sta; | ||
619 | } | ||
620 | /* Tx timer */ | ||
621 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
622 | sta_addba_resp_timer_expired; | ||
623 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
624 | (unsigned long)&sta->timer_to_tid[tid]; | ||
625 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
626 | |||
627 | /* create a new queue for this aggregation */ | ||
628 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
629 | |||
630 | /* case no queue is available to aggregation | ||
631 | * don't switch to aggregation */ | ||
632 | if (ret) { | ||
633 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
634 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | ||
635 | " tid %d\n", tid); | ||
636 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
637 | goto err_unlock_queue; | ||
638 | } | ||
639 | sdata = sta->sdata; | ||
640 | |||
641 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
642 | * call back right away, it must see that the flow has begun */ | ||
643 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
644 | |||
645 | if (local->ops->ampdu_action) | ||
646 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | ||
647 | ra, tid, &start_seq_num); | ||
648 | |||
649 | if (ret) { | ||
650 | /* No need to requeue the packets in the agg queue, since we | ||
651 | * held the tx lock: no packet could be enqueued to the newly | ||
652 | * allocated queue */ | ||
653 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
654 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
655 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
656 | " tid %d\n", tid); | ||
657 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
658 | *state = HT_AGG_STATE_IDLE; | ||
659 | goto err_unlock_queue; | ||
660 | } | ||
661 | |||
662 | /* Will put all the packets in the new SW queue */ | ||
663 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
664 | spin_unlock_bh(&sta->lock); | ||
665 | |||
666 | /* send an addBA request */ | ||
667 | sta->ampdu_mlme.dialog_token_allocator++; | ||
668 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | ||
669 | sta->ampdu_mlme.dialog_token_allocator; | ||
670 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
671 | |||
672 | |||
673 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, | ||
674 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | ||
675 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
676 | 0x40, 5000); | ||
677 | /* activate the timer for the recipient's addBA response */ | ||
678 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
679 | jiffies + ADDBA_RESP_INTERVAL; | ||
680 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
681 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
682 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
683 | #endif | ||
684 | goto exit; | ||
685 | |||
686 | err_unlock_queue: | ||
687 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
688 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
689 | ret = -EBUSY; | ||
690 | err_unlock_sta: | ||
691 | spin_unlock_bh(&sta->lock); | ||
692 | exit: | ||
693 | rcu_read_unlock(); | ||
694 | return ret; | ||
695 | } | ||
696 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
697 | |||
698 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | ||
699 | u8 *ra, u16 tid, | ||
700 | enum ieee80211_back_parties initiator) | ||
701 | { | ||
702 | struct ieee80211_local *local = hw_to_local(hw); | ||
703 | struct sta_info *sta; | ||
704 | u8 *state; | ||
705 | int ret = 0; | ||
706 | DECLARE_MAC_BUF(mac); | ||
707 | |||
708 | if (tid >= STA_TID_NUM) | ||
709 | return -EINVAL; | ||
710 | |||
711 | rcu_read_lock(); | ||
712 | sta = sta_info_get(local, ra); | ||
713 | if (!sta) { | ||
714 | rcu_read_unlock(); | ||
715 | return -ENOENT; | ||
716 | } | ||
717 | |||
718 | /* check if the TID is in aggregation */ | ||
719 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
720 | spin_lock_bh(&sta->lock); | ||
721 | |||
722 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
723 | ret = -ENOENT; | ||
724 | goto stop_BA_exit; | ||
725 | } | ||
726 | |||
727 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
728 | printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", | ||
729 | print_mac(mac, ra), tid); | ||
730 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
731 | |||
732 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
733 | |||
734 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
735 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
736 | |||
737 | if (local->ops->ampdu_action) | ||
738 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, | ||
739 | ra, tid, NULL); | ||
740 | |||
741 | /* case HW denied going back to legacy */ | ||
742 | if (ret) { | ||
743 | WARN_ON(ret != -EBUSY); | ||
744 | *state = HT_AGG_STATE_OPERATIONAL; | ||
745 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
746 | goto stop_BA_exit; | ||
747 | } | ||
748 | |||
749 | stop_BA_exit: | ||
750 | spin_unlock_bh(&sta->lock); | ||
751 | rcu_read_unlock(); | ||
752 | return ret; | ||
753 | } | ||
754 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
755 | |||
756 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
757 | { | ||
758 | struct ieee80211_local *local = hw_to_local(hw); | ||
759 | struct sta_info *sta; | ||
760 | u8 *state; | ||
761 | DECLARE_MAC_BUF(mac); | ||
762 | |||
763 | if (tid >= STA_TID_NUM) { | ||
764 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
765 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
766 | tid, STA_TID_NUM); | ||
767 | #endif | ||
768 | return; | ||
769 | } | ||
770 | |||
771 | rcu_read_lock(); | ||
772 | sta = sta_info_get(local, ra); | ||
773 | if (!sta) { | ||
774 | rcu_read_unlock(); | ||
775 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
776 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
777 | print_mac(mac, ra)); | ||
778 | #endif | ||
779 | return; | ||
780 | } | ||
781 | |||
782 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
783 | spin_lock_bh(&sta->lock); | ||
784 | |||
785 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
786 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
787 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | ||
788 | *state); | ||
789 | #endif | ||
790 | spin_unlock_bh(&sta->lock); | ||
791 | rcu_read_unlock(); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); | ||
796 | |||
797 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
798 | |||
799 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
800 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
801 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | ||
802 | #endif | ||
803 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
804 | } | ||
805 | spin_unlock_bh(&sta->lock); | ||
806 | rcu_read_unlock(); | ||
807 | } | ||
808 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
809 | |||
810 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | ||
811 | { | ||
812 | struct ieee80211_local *local = hw_to_local(hw); | ||
813 | struct sta_info *sta; | ||
814 | u8 *state; | ||
815 | int agg_queue; | ||
816 | DECLARE_MAC_BUF(mac); | ||
817 | |||
818 | if (tid >= STA_TID_NUM) { | ||
819 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
820 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
821 | tid, STA_TID_NUM); | ||
822 | #endif | ||
823 | return; | ||
824 | } | ||
825 | |||
826 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
827 | printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", | ||
828 | print_mac(mac, ra), tid); | ||
829 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
830 | |||
831 | rcu_read_lock(); | ||
832 | sta = sta_info_get(local, ra); | ||
833 | if (!sta) { | ||
834 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
835 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
836 | print_mac(mac, ra)); | ||
837 | #endif | ||
838 | rcu_read_unlock(); | ||
839 | return; | ||
840 | } | ||
841 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
842 | |||
843 | /* NOTE: no need to use sta->lock in this state check, as | ||
844 | * ieee80211_stop_tx_ba_session will let only one stop call to | ||
845 | * pass through per sta/tid | ||
846 | */ | ||
847 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | ||
848 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
849 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
850 | #endif | ||
851 | rcu_read_unlock(); | ||
852 | return; | ||
853 | } | ||
854 | |||
855 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | ||
856 | ieee80211_send_delba(sta->sdata->dev, ra, tid, | ||
857 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | ||
858 | |||
859 | agg_queue = sta->tid_to_tx_q[tid]; | ||
860 | |||
861 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | ||
862 | |||
863 | /* We just requeued the all the frames that were in the | ||
864 | * removed queue, and since we might miss a softirq we do | ||
865 | * netif_schedule_queue. ieee80211_wake_queue is not used | ||
866 | * here as this queue is not necessarily stopped | ||
867 | */ | ||
868 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); | ||
869 | spin_lock_bh(&sta->lock); | ||
870 | *state = HT_AGG_STATE_IDLE; | ||
871 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
872 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
873 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
874 | spin_unlock_bh(&sta->lock); | ||
875 | |||
876 | rcu_read_unlock(); | ||
877 | } | ||
878 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
879 | |||
880 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
881 | const u8 *ra, u16 tid) | ||
882 | { | ||
883 | struct ieee80211_local *local = hw_to_local(hw); | ||
884 | struct ieee80211_ra_tid *ra_tid; | ||
885 | struct sk_buff *skb = dev_alloc_skb(0); | ||
886 | |||
887 | if (unlikely(!skb)) { | ||
888 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
889 | if (net_ratelimit()) | ||
890 | printk(KERN_WARNING "%s: Not enough memory, " | ||
891 | "dropping start BA session", skb->dev->name); | ||
892 | #endif | ||
893 | return; | ||
894 | } | ||
895 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
896 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
897 | ra_tid->tid = tid; | ||
898 | |||
899 | skb->pkt_type = IEEE80211_ADDBA_MSG; | ||
900 | skb_queue_tail(&local->skb_queue, skb); | ||
901 | tasklet_schedule(&local->tasklet); | ||
902 | } | ||
903 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
904 | |||
905 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
906 | const u8 *ra, u16 tid) | ||
907 | { | ||
908 | struct ieee80211_local *local = hw_to_local(hw); | ||
909 | struct ieee80211_ra_tid *ra_tid; | ||
910 | struct sk_buff *skb = dev_alloc_skb(0); | ||
911 | |||
912 | if (unlikely(!skb)) { | ||
913 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
914 | if (net_ratelimit()) | ||
915 | printk(KERN_WARNING "%s: Not enough memory, " | ||
916 | "dropping stop BA session", skb->dev->name); | ||
917 | #endif | ||
918 | return; | ||
919 | } | ||
920 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
921 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
922 | ra_tid->tid = tid; | ||
923 | |||
924 | skb->pkt_type = IEEE80211_DELBA_MSG; | ||
925 | skb_queue_tail(&local->skb_queue, skb); | ||
926 | tasklet_schedule(&local->tasklet); | ||
927 | } | ||
928 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
929 | |||
930 | static void ieee80211_set_multicast_list(struct net_device *dev) | ||
931 | { | ||
932 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
933 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
934 | int allmulti, promisc, sdata_allmulti, sdata_promisc; | ||
935 | |||
936 | allmulti = !!(dev->flags & IFF_ALLMULTI); | ||
937 | promisc = !!(dev->flags & IFF_PROMISC); | ||
938 | sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); | ||
939 | sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); | ||
940 | |||
941 | if (allmulti != sdata_allmulti) { | ||
942 | if (dev->flags & IFF_ALLMULTI) | ||
943 | atomic_inc(&local->iff_allmultis); | ||
944 | else | ||
945 | atomic_dec(&local->iff_allmultis); | ||
946 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | ||
947 | } | ||
948 | |||
949 | if (promisc != sdata_promisc) { | ||
950 | if (dev->flags & IFF_PROMISC) | ||
951 | atomic_inc(&local->iff_promiscs); | ||
952 | else | ||
953 | atomic_dec(&local->iff_promiscs); | ||
954 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | ||
955 | } | ||
956 | |||
957 | dev_mc_sync(local->mdev, dev); | ||
958 | } | ||
959 | |||
960 | static const struct header_ops ieee80211_header_ops = { | ||
961 | .create = eth_header, | ||
962 | .parse = header_parse_80211, | ||
963 | .rebuild = eth_rebuild_header, | ||
964 | .cache = eth_header_cache, | ||
965 | .cache_update = eth_header_cache_update, | ||
966 | }; | ||
967 | |||
968 | void ieee80211_if_setup(struct net_device *dev) | ||
969 | { | ||
970 | ether_setup(dev); | ||
971 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
972 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
973 | dev->set_multicast_list = ieee80211_set_multicast_list; | ||
974 | dev->change_mtu = ieee80211_change_mtu; | ||
975 | dev->open = ieee80211_open; | ||
976 | dev->stop = ieee80211_stop; | ||
977 | dev->destructor = free_netdev; | ||
978 | } | ||
979 | |||
980 | /* everything else */ | 152 | /* everything else */ |
981 | 153 | ||
982 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | 154 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) |
@@ -987,18 +159,21 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
987 | if (WARN_ON(!netif_running(sdata->dev))) | 159 | if (WARN_ON(!netif_running(sdata->dev))) |
988 | return 0; | 160 | return 0; |
989 | 161 | ||
162 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
163 | return -EINVAL; | ||
164 | |||
990 | if (!local->ops->config_interface) | 165 | if (!local->ops->config_interface) |
991 | return 0; | 166 | return 0; |
992 | 167 | ||
993 | memset(&conf, 0, sizeof(conf)); | 168 | memset(&conf, 0, sizeof(conf)); |
994 | conf.changed = changed; | 169 | conf.changed = changed; |
995 | 170 | ||
996 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 171 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
997 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 172 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
998 | conf.bssid = sdata->u.sta.bssid; | 173 | conf.bssid = sdata->u.sta.bssid; |
999 | conf.ssid = sdata->u.sta.ssid; | 174 | conf.ssid = sdata->u.sta.ssid; |
1000 | conf.ssid_len = sdata->u.sta.ssid_len; | 175 | conf.ssid_len = sdata->u.sta.ssid_len; |
1001 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 176 | } else if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1002 | conf.bssid = sdata->dev->dev_addr; | 177 | conf.bssid = sdata->dev->dev_addr; |
1003 | conf.ssid = sdata->u.ap.ssid; | 178 | conf.ssid = sdata->u.ap.ssid; |
1004 | conf.ssid_len = sdata->u.ap.ssid_len; | 179 | conf.ssid_len = sdata->u.ap.ssid_len; |
@@ -1027,7 +202,7 @@ int ieee80211_hw_config(struct ieee80211_local *local) | |||
1027 | struct ieee80211_channel *chan; | 202 | struct ieee80211_channel *chan; |
1028 | int ret = 0; | 203 | int ret = 0; |
1029 | 204 | ||
1030 | if (local->sta_sw_scanning) | 205 | if (local->sw_scanning) |
1031 | chan = local->scan_channel; | 206 | chan = local->scan_channel; |
1032 | else | 207 | else |
1033 | chan = local->oper_channel; | 208 | chan = local->oper_channel; |
@@ -1099,8 +274,8 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | |||
1099 | ht_conf.ht_supported = 1; | 274 | ht_conf.ht_supported = 1; |
1100 | 275 | ||
1101 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; | 276 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; |
1102 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); | 277 | ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS); |
1103 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; | 278 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS; |
1104 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | 279 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; |
1105 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | 280 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; |
1106 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | 281 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; |
@@ -1152,6 +327,9 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1152 | { | 327 | { |
1153 | struct ieee80211_local *local = sdata->local; | 328 | struct ieee80211_local *local = sdata->local; |
1154 | 329 | ||
330 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
331 | return; | ||
332 | |||
1155 | if (!changed) | 333 | if (!changed) |
1156 | return; | 334 | return; |
1157 | 335 | ||
@@ -1162,10 +340,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1162 | changed); | 340 | changed); |
1163 | } | 341 | } |
1164 | 342 | ||
1165 | u32 ieee80211_reset_erp_info(struct net_device *dev) | 343 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
1166 | { | 344 | { |
1167 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1168 | |||
1169 | sdata->bss_conf.use_cts_prot = 0; | 345 | sdata->bss_conf.use_cts_prot = 0; |
1170 | sdata->bss_conf.use_short_preamble = 0; | 346 | sdata->bss_conf.use_short_preamble = 0; |
1171 | return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; | 347 | return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; |
@@ -1244,9 +420,10 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | |||
1244 | struct ieee80211_key *key, | 420 | struct ieee80211_key *key, |
1245 | struct sk_buff *skb) | 421 | struct sk_buff *skb) |
1246 | { | 422 | { |
1247 | int hdrlen, iv_len, mic_len; | 423 | unsigned int hdrlen, iv_len, mic_len; |
424 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1248 | 425 | ||
1249 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 426 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1250 | 427 | ||
1251 | if (!key) | 428 | if (!key) |
1252 | goto no_key; | 429 | goto no_key; |
@@ -1268,24 +445,20 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | |||
1268 | goto no_key; | 445 | goto no_key; |
1269 | } | 446 | } |
1270 | 447 | ||
1271 | if (skb->len >= mic_len && | 448 | if (skb->len >= hdrlen + mic_len && |
1272 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 449 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
1273 | skb_trim(skb, skb->len - mic_len); | 450 | skb_trim(skb, skb->len - mic_len); |
1274 | if (skb->len >= iv_len && skb->len > hdrlen) { | 451 | if (skb->len >= hdrlen + iv_len) { |
1275 | memmove(skb->data + iv_len, skb->data, hdrlen); | 452 | memmove(skb->data + iv_len, skb->data, hdrlen); |
1276 | skb_pull(skb, iv_len); | 453 | hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); |
1277 | } | 454 | } |
1278 | 455 | ||
1279 | no_key: | 456 | no_key: |
1280 | { | 457 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
1281 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 458 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1282 | u16 fc = le16_to_cpu(hdr->frame_control); | 459 | memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, |
1283 | if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { | 460 | hdrlen - IEEE80211_QOS_CTL_LEN); |
1284 | fc &= ~IEEE80211_STYPE_QOS_DATA; | 461 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); |
1285 | hdr->frame_control = cpu_to_le16(fc); | ||
1286 | memmove(skb->data + 2, skb->data, hdrlen - 2); | ||
1287 | skb_pull(skb, 2); | ||
1288 | } | ||
1289 | } | 462 | } |
1290 | } | 463 | } |
1291 | 464 | ||
@@ -1369,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1369 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 542 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1370 | u16 frag, type; | 543 | u16 frag, type; |
1371 | __le16 fc; | 544 | __le16 fc; |
545 | struct ieee80211_supported_band *sband; | ||
1372 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 546 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
1373 | struct ieee80211_sub_if_data *sdata; | 547 | struct ieee80211_sub_if_data *sdata; |
1374 | struct net_device *prev_dev = NULL; | 548 | struct net_device *prev_dev = NULL; |
@@ -1376,47 +550,48 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1376 | 550 | ||
1377 | rcu_read_lock(); | 551 | rcu_read_lock(); |
1378 | 552 | ||
1379 | if (info->status.excessive_retries) { | 553 | sta = sta_info_get(local, hdr->addr1); |
1380 | sta = sta_info_get(local, hdr->addr1); | 554 | |
1381 | if (sta) { | 555 | if (sta) { |
1382 | if (test_sta_flags(sta, WLAN_STA_PS)) { | 556 | if (info->status.excessive_retries && |
1383 | /* | 557 | test_sta_flags(sta, WLAN_STA_PS)) { |
1384 | * The STA is in power save mode, so assume | 558 | /* |
1385 | * that this TX packet failed because of that. | 559 | * The STA is in power save mode, so assume |
1386 | */ | 560 | * that this TX packet failed because of that. |
1387 | ieee80211_handle_filtered_frame(local, sta, skb); | 561 | */ |
1388 | rcu_read_unlock(); | 562 | ieee80211_handle_filtered_frame(local, sta, skb); |
1389 | return; | 563 | rcu_read_unlock(); |
1390 | } | 564 | return; |
1391 | } | 565 | } |
1392 | } | ||
1393 | 566 | ||
1394 | fc = hdr->frame_control; | 567 | fc = hdr->frame_control; |
568 | |||
569 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
570 | (ieee80211_is_data_qos(fc))) { | ||
571 | u16 tid, ssn; | ||
572 | u8 *qc; | ||
1395 | 573 | ||
1396 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
1397 | (ieee80211_is_data_qos(fc))) { | ||
1398 | u16 tid, ssn; | ||
1399 | u8 *qc; | ||
1400 | sta = sta_info_get(local, hdr->addr1); | ||
1401 | if (sta) { | ||
1402 | qc = ieee80211_get_qos_ctl(hdr); | 574 | qc = ieee80211_get_qos_ctl(hdr); |
1403 | tid = qc[0] & 0xf; | 575 | tid = qc[0] & 0xf; |
1404 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) | 576 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) |
1405 | & IEEE80211_SCTL_SEQ); | 577 | & IEEE80211_SCTL_SEQ); |
1406 | ieee80211_send_bar(sta->sdata->dev, hdr->addr1, | 578 | ieee80211_send_bar(sta->sdata, hdr->addr1, |
1407 | tid, ssn); | 579 | tid, ssn); |
1408 | } | 580 | } |
1409 | } | ||
1410 | 581 | ||
1411 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | 582 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
1412 | sta = sta_info_get(local, hdr->addr1); | ||
1413 | if (sta) { | ||
1414 | ieee80211_handle_filtered_frame(local, sta, skb); | 583 | ieee80211_handle_filtered_frame(local, sta, skb); |
1415 | rcu_read_unlock(); | 584 | rcu_read_unlock(); |
1416 | return; | 585 | return; |
586 | } else { | ||
587 | if (info->status.excessive_retries) | ||
588 | sta->tx_retry_failed++; | ||
589 | sta->tx_retry_count += info->status.retry_count; | ||
1417 | } | 590 | } |
1418 | } else | 591 | |
1419 | rate_control_tx_status(local->mdev, skb); | 592 | sband = local->hw.wiphy->bands[info->band]; |
593 | rate_control_tx_status(local, sband, sta, skb); | ||
594 | } | ||
1420 | 595 | ||
1421 | rcu_read_unlock(); | 596 | rcu_read_unlock(); |
1422 | 597 | ||
@@ -1504,7 +679,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1504 | 679 | ||
1505 | rcu_read_lock(); | 680 | rcu_read_lock(); |
1506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 681 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
1507 | if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) { | 682 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
1508 | if (!netif_running(sdata->dev)) | 683 | if (!netif_running(sdata->dev)) |
1509 | continue; | 684 | continue; |
1510 | 685 | ||
@@ -1580,8 +755,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1580 | 755 | ||
1581 | local->hw.queues = 1; /* default */ | 756 | local->hw.queues = 1; /* default */ |
1582 | 757 | ||
1583 | local->bridge_packets = 1; | ||
1584 | |||
1585 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 758 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
1586 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | 759 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; |
1587 | local->short_retry_limit = 7; | 760 | local->short_retry_limit = 7; |
@@ -1592,7 +765,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1592 | 765 | ||
1593 | spin_lock_init(&local->key_lock); | 766 | spin_lock_init(&local->key_lock); |
1594 | 767 | ||
1595 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); | 768 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
1596 | 769 | ||
1597 | sta_info_init(local); | 770 | sta_info_init(local); |
1598 | 771 | ||
@@ -1619,7 +792,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1619 | int result; | 792 | int result; |
1620 | enum ieee80211_band band; | 793 | enum ieee80211_band band; |
1621 | struct net_device *mdev; | 794 | struct net_device *mdev; |
1622 | struct wireless_dev *mwdev; | 795 | struct ieee80211_master_priv *mpriv; |
1623 | 796 | ||
1624 | /* | 797 | /* |
1625 | * generic code guarantees at least one band, | 798 | * generic code guarantees at least one band, |
@@ -1639,6 +812,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1639 | } | 812 | } |
1640 | } | 813 | } |
1641 | 814 | ||
815 | /* if low-level driver supports AP, we also support VLAN */ | ||
816 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) | ||
817 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | ||
818 | |||
819 | /* mac80211 always supports monitor */ | ||
820 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | ||
821 | |||
1642 | result = wiphy_register(local->hw.wiphy); | 822 | result = wiphy_register(local->hw.wiphy); |
1643 | if (result < 0) | 823 | if (result < 0) |
1644 | return result; | 824 | return result; |
@@ -1654,16 +834,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1654 | if (hw->queues < 4) | 834 | if (hw->queues < 4) |
1655 | hw->ampdu_queues = 0; | 835 | hw->ampdu_queues = 0; |
1656 | 836 | ||
1657 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), | 837 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), |
1658 | "wmaster%d", ether_setup, | 838 | "wmaster%d", ether_setup, |
1659 | ieee80211_num_queues(hw)); | 839 | ieee80211_num_queues(hw)); |
1660 | if (!mdev) | 840 | if (!mdev) |
1661 | goto fail_mdev_alloc; | 841 | goto fail_mdev_alloc; |
1662 | 842 | ||
1663 | mwdev = netdev_priv(mdev); | 843 | mpriv = netdev_priv(mdev); |
1664 | mdev->ieee80211_ptr = mwdev; | 844 | mpriv->local = local; |
1665 | mwdev->wiphy = local->hw.wiphy; | ||
1666 | |||
1667 | local->mdev = mdev; | 845 | local->mdev = mdev; |
1668 | 846 | ||
1669 | ieee80211_rx_bss_list_init(local); | 847 | ieee80211_rx_bss_list_init(local); |
@@ -1745,7 +923,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1745 | 923 | ||
1746 | /* add one default STA interface */ | 924 | /* add one default STA interface */ |
1747 | result = ieee80211_if_add(local, "wlan%d", NULL, | 925 | result = ieee80211_if_add(local, "wlan%d", NULL, |
1748 | IEEE80211_IF_TYPE_STA, NULL); | 926 | NL80211_IFTYPE_STATION, NULL); |
1749 | if (result) | 927 | if (result) |
1750 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 928 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", |
1751 | wiphy_name(local->hw.wiphy)); | 929 | wiphy_name(local->hw.wiphy)); |
@@ -1837,6 +1015,10 @@ static int __init ieee80211_init(void) | |||
1837 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + | 1015 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + |
1838 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); | 1016 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); |
1839 | 1017 | ||
1018 | ret = rc80211_minstrel_init(); | ||
1019 | if (ret) | ||
1020 | return ret; | ||
1021 | |||
1840 | ret = rc80211_pid_init(); | 1022 | ret = rc80211_pid_init(); |
1841 | if (ret) | 1023 | if (ret) |
1842 | return ret; | 1024 | return ret; |
@@ -1849,6 +1031,7 @@ static int __init ieee80211_init(void) | |||
1849 | static void __exit ieee80211_exit(void) | 1031 | static void __exit ieee80211_exit(void) |
1850 | { | 1032 | { |
1851 | rc80211_pid_exit(); | 1033 | rc80211_pid_exit(); |
1034 | rc80211_minstrel_exit(); | ||
1852 | 1035 | ||
1853 | /* | 1036 | /* |
1854 | * For key todo, it'll be empty by now but the work | 1037 | * For key todo, it'll be empty by now but the work |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 35f2f95f2fa7..8013277924f2 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,19 +38,28 @@ 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 | * |
41 | * @ie: information elements of a management frame from the mesh peer | 54 | * @ie: information elements of a management frame from the mesh peer |
42 | * @dev: local mesh interface | 55 | * @sdata: local mesh subif |
43 | * | 56 | * |
44 | * This function checks if the mesh configuration of a mesh point matches the | 57 | * This function checks if the mesh configuration of a mesh point matches the |
45 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. | 58 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. |
46 | */ | 59 | */ |
47 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) | 60 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) |
48 | { | 61 | { |
49 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 62 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
50 | struct ieee80211_if_sta *sta = &sdata->u.sta; | ||
51 | 63 | ||
52 | /* | 64 | /* |
53 | * As support for each feature is added, check for matching | 65 | * As support for each feature is added, check for matching |
@@ -59,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) | |||
59 | * - MDA enabled | 71 | * - MDA enabled |
60 | * - Power management control on fc | 72 | * - Power management control on fc |
61 | */ | 73 | */ |
62 | if (sta->mesh_id_len == ie->mesh_id_len && | 74 | if (ifmsh->mesh_id_len == ie->mesh_id_len && |
63 | 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 && |
64 | 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 && |
65 | 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 && |
66 | 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) |
67 | return true; | 79 | return true; |
68 | 80 | ||
69 | return false; | 81 | return false; |
@@ -73,10 +85,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) | |||
73 | * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links | 85 | * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links |
74 | * | 86 | * |
75 | * @ie: information elements of a management frame from the mesh peer | 87 | * @ie: information elements of a management frame from the mesh peer |
76 | * @dev: local mesh interface | ||
77 | */ | 88 | */ |
78 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, | 89 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
79 | struct net_device *dev) | ||
80 | { | 90 | { |
81 | return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; | 91 | return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; |
82 | } | 92 | } |
@@ -98,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
98 | */ | 108 | */ |
99 | free_plinks = mesh_plink_availables(sdata); | 109 | free_plinks = mesh_plink_availables(sdata); |
100 | 110 | ||
101 | if (free_plinks != sdata->u.sta.accepting_plinks) | 111 | if (free_plinks != sdata->u.mesh.accepting_plinks) |
102 | ieee80211_sta_timer((unsigned long) sdata); | 112 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
103 | } | 113 | } |
104 | 114 | ||
105 | void mesh_ids_set_default(struct ieee80211_if_sta *sta) | 115 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) |
106 | { | 116 | { |
107 | u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; | 117 | u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; |
108 | 118 | ||
@@ -111,28 +121,26 @@ void mesh_ids_set_default(struct ieee80211_if_sta *sta) | |||
111 | memcpy(sta->mesh_cc_id, def_id, 4); | 121 | memcpy(sta->mesh_cc_id, def_id, 4); |
112 | } | 122 | } |
113 | 123 | ||
114 | int mesh_rmc_init(struct net_device *dev) | 124 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
115 | { | 125 | { |
116 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
117 | int i; | 126 | int i; |
118 | 127 | ||
119 | sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); | 128 | sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); |
120 | if (!sdata->u.sta.rmc) | 129 | if (!sdata->u.mesh.rmc) |
121 | return -ENOMEM; | 130 | return -ENOMEM; |
122 | sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; | 131 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; |
123 | for (i = 0; i < RMC_BUCKETS; i++) | 132 | for (i = 0; i < RMC_BUCKETS; i++) |
124 | INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); | 133 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); |
125 | return 0; | 134 | return 0; |
126 | } | 135 | } |
127 | 136 | ||
128 | void mesh_rmc_free(struct net_device *dev) | 137 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) |
129 | { | 138 | { |
130 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 139 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
131 | struct mesh_rmc *rmc = sdata->u.sta.rmc; | ||
132 | struct rmc_entry *p, *n; | 140 | struct rmc_entry *p, *n; |
133 | int i; | 141 | int i; |
134 | 142 | ||
135 | if (!sdata->u.sta.rmc) | 143 | if (!sdata->u.mesh.rmc) |
136 | return; | 144 | return; |
137 | 145 | ||
138 | for (i = 0; i < RMC_BUCKETS; i++) | 146 | for (i = 0; i < RMC_BUCKETS; i++) |
@@ -142,7 +150,7 @@ void mesh_rmc_free(struct net_device *dev) | |||
142 | } | 150 | } |
143 | 151 | ||
144 | kfree(rmc); | 152 | kfree(rmc); |
145 | sdata->u.sta.rmc = NULL; | 153 | sdata->u.mesh.rmc = NULL; |
146 | } | 154 | } |
147 | 155 | ||
148 | /** | 156 | /** |
@@ -158,10 +166,9 @@ void mesh_rmc_free(struct net_device *dev) | |||
158 | * it. | 166 | * it. |
159 | */ | 167 | */ |
160 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | 168 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, |
161 | struct net_device *dev) | 169 | struct ieee80211_sub_if_data *sdata) |
162 | { | 170 | { |
163 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 171 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
164 | struct mesh_rmc *rmc = sdata->u.sta.rmc; | ||
165 | u32 seqnum = 0; | 172 | u32 seqnum = 0; |
166 | int entries = 0; | 173 | int entries = 0; |
167 | u8 idx; | 174 | u8 idx; |
@@ -194,10 +201,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
194 | return 0; | 201 | return 0; |
195 | } | 202 | } |
196 | 203 | ||
197 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | 204 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) |
198 | { | 205 | { |
199 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 206 | struct ieee80211_local *local = sdata->local; |
200 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
201 | struct ieee80211_supported_band *sband; | 207 | struct ieee80211_supported_band *sband; |
202 | u8 *pos; | 208 | u8 *pos; |
203 | int len, i, rate; | 209 | int len, i, rate; |
@@ -224,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | |||
224 | } | 230 | } |
225 | } | 231 | } |
226 | 232 | ||
227 | pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); | 233 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); |
228 | *pos++ = WLAN_EID_MESH_ID; | 234 | *pos++ = WLAN_EID_MESH_ID; |
229 | *pos++ = sdata->u.sta.mesh_id_len; | 235 | *pos++ = sdata->u.mesh.mesh_id_len; |
230 | if (sdata->u.sta.mesh_id_len) | 236 | if (sdata->u.mesh.mesh_id_len) |
231 | 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); |
232 | 238 | ||
233 | pos = skb_put(skb, 21); | 239 | pos = skb_put(skb, 21); |
234 | *pos++ = WLAN_EID_MESH_CONFIG; | 240 | *pos++ = WLAN_EID_MESH_CONFIG; |
@@ -237,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | |||
237 | *pos++ = 1; | 243 | *pos++ = 1; |
238 | 244 | ||
239 | /* Active path selection protocol ID */ | 245 | /* Active path selection protocol ID */ |
240 | memcpy(pos, sdata->u.sta.mesh_pp_id, 4); | 246 | memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); |
241 | pos += 4; | 247 | pos += 4; |
242 | 248 | ||
243 | /* Active path selection metric ID */ | 249 | /* Active path selection metric ID */ |
244 | memcpy(pos, sdata->u.sta.mesh_pm_id, 4); | 250 | memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); |
245 | pos += 4; | 251 | pos += 4; |
246 | 252 | ||
247 | /* Congestion control mode identifier */ | 253 | /* Congestion control mode identifier */ |
248 | memcpy(pos, sdata->u.sta.mesh_cc_id, 4); | 254 | memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); |
249 | pos += 4; | 255 | pos += 4; |
250 | 256 | ||
251 | /* Channel precedence: | 257 | /* Channel precedence: |
@@ -255,17 +261,17 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | |||
255 | pos += 4; | 261 | pos += 4; |
256 | 262 | ||
257 | /* Mesh capability */ | 263 | /* Mesh capability */ |
258 | sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); | 264 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); |
259 | *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; | 265 | *pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00; |
260 | *pos++ = 0x00; | 266 | *pos++ = 0x00; |
261 | 267 | ||
262 | return; | 268 | return; |
263 | } | 269 | } |
264 | 270 | ||
265 | u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl) | 271 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
266 | { | 272 | { |
267 | /* Use last four bytes of hw addr and interface index as hash index */ | 273 | /* Use last four bytes of hw addr and interface index as hash index */ |
268 | return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd) | 274 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) |
269 | & tbl->hash_mask; | 275 | & tbl->hash_mask; |
270 | } | 276 | } |
271 | 277 | ||
@@ -344,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
344 | { | 350 | { |
345 | struct ieee80211_sub_if_data *sdata = | 351 | struct ieee80211_sub_if_data *sdata = |
346 | (struct ieee80211_sub_if_data *) data; | 352 | (struct ieee80211_sub_if_data *) data; |
347 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
348 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 354 | struct ieee80211_local *local = sdata->local; |
349 | 355 | ||
350 | queue_work(local->hw.workqueue, &ifsta->work); | 356 | queue_work(local->hw.workqueue, &ifmsh->work); |
351 | } | 357 | } |
352 | 358 | ||
353 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | 359 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) |
@@ -399,50 +405,264 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
399 | struct ieee80211_sub_if_data *sdata) | 405 | struct ieee80211_sub_if_data *sdata) |
400 | { | 406 | { |
401 | meshhdr->flags = 0; | 407 | meshhdr->flags = 0; |
402 | meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; | 408 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
403 | 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); |
404 | sdata->u.sta.mesh_seqnum++; | 410 | sdata->u.mesh.mesh_seqnum++; |
405 | 411 | ||
406 | return 6; | 412 | return 6; |
407 | } | 413 | } |
408 | 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 | * If the timer fired while we waited for it, it will have | ||
453 | * requeued the work. Now the work will be running again | ||
454 | * but will not rearm the timer again because it checks | ||
455 | * whether the interface is running, which, at this point, | ||
456 | * it no longer is. | ||
457 | */ | ||
458 | cancel_work_sync(&sdata->u.mesh.work); | ||
459 | |||
460 | /* | ||
461 | * When we get here, the interface is marked down. | ||
462 | * Call synchronize_rcu() to wait for the RX path | ||
463 | * should it be using the interface and enqueuing | ||
464 | * frames at this very time on another CPU. | ||
465 | */ | ||
466 | synchronize_rcu(); | ||
467 | skb_queue_purge(&sdata->u.mesh.skb_queue); | ||
468 | } | ||
469 | |||
470 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | ||
471 | u16 stype, | ||
472 | struct ieee80211_mgmt *mgmt, | ||
473 | size_t len, | ||
474 | struct ieee80211_rx_status *rx_status) | ||
475 | { | ||
476 | struct ieee80211_local *local= sdata->local; | ||
477 | struct ieee802_11_elems elems; | ||
478 | struct ieee80211_channel *channel; | ||
479 | u64 supp_rates = 0; | ||
480 | size_t baselen; | ||
481 | int freq; | ||
482 | enum ieee80211_band band = rx_status->band; | ||
483 | |||
484 | /* ignore ProbeResp to foreign address */ | ||
485 | if (stype == IEEE80211_STYPE_PROBE_RESP && | ||
486 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | ||
487 | return; | ||
488 | |||
489 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | ||
490 | if (baselen > len) | ||
491 | return; | ||
492 | |||
493 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | ||
494 | &elems); | ||
495 | |||
496 | if (elems.ds_params && elems.ds_params_len == 1) | ||
497 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | ||
498 | else | ||
499 | freq = rx_status->freq; | ||
500 | |||
501 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
502 | |||
503 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
504 | return; | ||
505 | |||
506 | if (elems.mesh_id && elems.mesh_config && | ||
507 | mesh_matches_local(&elems, sdata)) { | ||
508 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); | ||
509 | |||
510 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, | ||
511 | mesh_peer_accepts_plinks(&elems)); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | ||
516 | struct ieee80211_mgmt *mgmt, | ||
517 | size_t len, | ||
518 | struct ieee80211_rx_status *rx_status) | ||
519 | { | ||
520 | switch (mgmt->u.action.category) { | ||
521 | case PLINK_CATEGORY: | ||
522 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | ||
523 | break; | ||
524 | case MESH_PATH_SEL_CATEGORY: | ||
525 | mesh_rx_path_sel_frame(sdata, mgmt, len); | ||
526 | break; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
531 | struct sk_buff *skb) | ||
532 | { | ||
533 | struct ieee80211_rx_status *rx_status; | ||
534 | struct ieee80211_if_mesh *ifmsh; | ||
535 | struct ieee80211_mgmt *mgmt; | ||
536 | u16 stype; | ||
537 | |||
538 | ifmsh = &sdata->u.mesh; | ||
539 | |||
540 | rx_status = (struct ieee80211_rx_status *) skb->cb; | ||
541 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
542 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | ||
543 | |||
544 | switch (stype) { | ||
545 | case IEEE80211_STYPE_PROBE_RESP: | ||
546 | case IEEE80211_STYPE_BEACON: | ||
547 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, | ||
548 | rx_status); | ||
549 | break; | ||
550 | case IEEE80211_STYPE_ACTION: | ||
551 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); | ||
552 | break; | ||
553 | } | ||
554 | |||
555 | kfree_skb(skb); | ||
556 | } | ||
557 | |||
558 | static void ieee80211_mesh_work(struct work_struct *work) | ||
559 | { | ||
560 | struct ieee80211_sub_if_data *sdata = | ||
561 | container_of(work, struct ieee80211_sub_if_data, u.mesh.work); | ||
562 | struct ieee80211_local *local = sdata->local; | ||
563 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
564 | struct sk_buff *skb; | ||
565 | |||
566 | if (!netif_running(sdata->dev)) | ||
567 | return; | ||
568 | |||
569 | if (local->sw_scanning || local->hw_scanning) | ||
570 | return; | ||
571 | |||
572 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) | ||
573 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | ||
574 | |||
575 | if (ifmsh->preq_queue_len && | ||
576 | time_after(jiffies, | ||
577 | ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) | ||
578 | mesh_path_start_discovery(sdata); | ||
579 | |||
580 | if (ifmsh->housekeeping) | ||
581 | ieee80211_mesh_housekeeping(sdata, ifmsh); | ||
582 | } | ||
583 | |||
584 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | ||
585 | { | ||
586 | struct ieee80211_sub_if_data *sdata; | ||
587 | |||
588 | rcu_read_lock(); | ||
589 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
590 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
591 | queue_work(local->hw.workqueue, &sdata->u.mesh.work); | ||
592 | rcu_read_unlock(); | ||
593 | } | ||
594 | |||
409 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | 595 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) |
410 | { | 596 | { |
411 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 597 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
412 | 598 | ||
413 | ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; | 599 | INIT_WORK(&ifmsh->work, ieee80211_mesh_work); |
414 | ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | 600 | setup_timer(&ifmsh->housekeeping_timer, |
415 | ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | 601 | ieee80211_mesh_housekeeping_timer, |
416 | ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | 602 | (unsigned long) sdata); |
417 | ifsta->mshcfg.dot11MeshTTL = MESH_TTL; | 603 | skb_queue_head_init(&sdata->u.mesh.skb_queue); |
418 | ifsta->mshcfg.auto_open_plinks = true; | 604 | |
419 | ifsta->mshcfg.dot11MeshMaxPeerLinks = | 605 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; |
606 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | ||
607 | ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | ||
608 | ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | ||
609 | ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; | ||
610 | ifmsh->mshcfg.auto_open_plinks = true; | ||
611 | ifmsh->mshcfg.dot11MeshMaxPeerLinks = | ||
420 | MESH_MAX_ESTAB_PLINKS; | 612 | MESH_MAX_ESTAB_PLINKS; |
421 | ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = | 613 | ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = |
422 | MESH_PATH_TIMEOUT; | 614 | MESH_PATH_TIMEOUT; |
423 | ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = | 615 | ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = |
424 | MESH_PREQ_MIN_INT; | 616 | MESH_PREQ_MIN_INT; |
425 | ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = | 617 | ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = |
426 | MESH_DIAM_TRAVERSAL_TIME; | 618 | MESH_DIAM_TRAVERSAL_TIME; |
427 | ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = | 619 | ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = |
428 | MESH_MAX_PREQ_RETRIES; | 620 | MESH_MAX_PREQ_RETRIES; |
429 | ifsta->mshcfg.path_refresh_time = | 621 | ifmsh->mshcfg.path_refresh_time = |
430 | MESH_PATH_REFRESH_TIME; | 622 | MESH_PATH_REFRESH_TIME; |
431 | ifsta->mshcfg.min_discovery_timeout = | 623 | ifmsh->mshcfg.min_discovery_timeout = |
432 | MESH_MIN_DISCOVERY_TIMEOUT; | 624 | MESH_MIN_DISCOVERY_TIMEOUT; |
433 | ifsta->accepting_plinks = true; | 625 | ifmsh->accepting_plinks = true; |
434 | ifsta->preq_id = 0; | 626 | ifmsh->preq_id = 0; |
435 | ifsta->dsn = 0; | 627 | ifmsh->dsn = 0; |
436 | atomic_set(&ifsta->mpaths, 0); | 628 | atomic_set(&ifmsh->mpaths, 0); |
437 | mesh_rmc_init(sdata->dev); | 629 | mesh_rmc_init(sdata); |
438 | ifsta->last_preq = jiffies; | 630 | ifmsh->last_preq = jiffies; |
439 | /* Allocate all mesh structures when creating the first mesh interface. */ | 631 | /* Allocate all mesh structures when creating the first mesh interface. */ |
440 | if (!mesh_allocated) | 632 | if (!mesh_allocated) |
441 | ieee80211s_init(); | 633 | ieee80211s_init(); |
442 | mesh_ids_set_default(ifsta); | 634 | mesh_ids_set_default(ifmsh); |
443 | setup_timer(&ifsta->mesh_path_timer, | 635 | setup_timer(&ifmsh->mesh_path_timer, |
444 | ieee80211_mesh_path_timer, | 636 | ieee80211_mesh_path_timer, |
445 | (unsigned long) sdata); | 637 | (unsigned long) sdata); |
446 | INIT_LIST_HEAD(&ifsta->preq_queue.list); | 638 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
447 | spin_lock_init(&ifsta->mesh_preq_queue_lock); | 639 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
640 | } | ||
641 | |||
642 | ieee80211_rx_result | ||
643 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
644 | struct ieee80211_rx_status *rx_status) | ||
645 | { | ||
646 | struct ieee80211_local *local = sdata->local; | ||
647 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
648 | struct ieee80211_mgmt *mgmt; | ||
649 | u16 fc; | ||
650 | |||
651 | if (skb->len < 24) | ||
652 | return RX_DROP_MONITOR; | ||
653 | |||
654 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
655 | fc = le16_to_cpu(mgmt->frame_control); | ||
656 | |||
657 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
658 | case IEEE80211_STYPE_PROBE_RESP: | ||
659 | case IEEE80211_STYPE_BEACON: | ||
660 | case IEEE80211_STYPE_ACTION: | ||
661 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); | ||
662 | skb_queue_tail(&ifmsh->skb_queue, skb); | ||
663 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
664 | return RX_QUEUED; | ||
665 | } | ||
666 | |||
667 | return RX_CONTINUE; | ||
448 | } | 668 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 7495fbb0d211..e10471c6ba42 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -47,7 +47,7 @@ enum mesh_path_flags { | |||
47 | * struct mesh_path - mac80211 mesh path structure | 47 | * struct mesh_path - mac80211 mesh path structure |
48 | * | 48 | * |
49 | * @dst: mesh path destination mac address | 49 | * @dst: mesh path destination mac address |
50 | * @dev: mesh path device | 50 | * @sdata: mesh subif |
51 | * @next_hop: mesh neighbor to which frames for this destination will be | 51 | * @next_hop: mesh neighbor to which frames for this destination will be |
52 | * forwarded | 52 | * forwarded |
53 | * @timer: mesh path discovery timer | 53 | * @timer: mesh path discovery timer |
@@ -64,14 +64,15 @@ enum mesh_path_flags { | |||
64 | * @state_lock: mesh pat state lock | 64 | * @state_lock: mesh pat state lock |
65 | * | 65 | * |
66 | * | 66 | * |
67 | * The combination of dst and dev is unique in the mesh path table. Since the | 67 | * The combination of dst and sdata is unique in the mesh path table. Since the |
68 | * next_hop STA is only protected by RCU as well, deleting the STA must also | 68 | * next_hop STA is only protected by RCU as well, deleting the STA must also |
69 | * remove/substitute the mesh_path structure and wait until that is no longer | 69 | * remove/substitute the mesh_path structure and wait until that is no longer |
70 | * reachable before destroying the STA completely. | 70 | * reachable before destroying the STA completely. |
71 | */ | 71 | */ |
72 | struct mesh_path { | 72 | struct mesh_path { |
73 | u8 dst[ETH_ALEN]; | 73 | u8 dst[ETH_ALEN]; |
74 | struct net_device *dev; | 74 | u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ |
75 | struct ieee80211_sub_if_data *sdata; | ||
75 | struct sta_info *next_hop; | 76 | struct sta_info *next_hop; |
76 | struct timer_list timer; | 77 | struct timer_list timer; |
77 | struct sk_buff_head frame_queue; | 78 | struct sk_buff_head frame_queue; |
@@ -203,67 +204,82 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); | |||
203 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 204 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
204 | struct ieee80211_sub_if_data *sdata); | 205 | struct ieee80211_sub_if_data *sdata); |
205 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 206 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
206 | struct net_device *dev); | 207 | struct ieee80211_sub_if_data *sdata); |
207 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev); | 208 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
208 | void mesh_ids_set_default(struct ieee80211_if_sta *sta); | 209 | struct ieee80211_sub_if_data *sdata); |
209 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev); | 210 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
210 | void mesh_rmc_free(struct net_device *dev); | 211 | void mesh_mgmt_ies_add(struct sk_buff *skb, |
211 | int mesh_rmc_init(struct net_device *dev); | 212 | struct ieee80211_sub_if_data *sdata); |
213 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | ||
214 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | ||
212 | void ieee80211s_init(void); | 215 | void ieee80211s_init(void); |
213 | void ieee80211s_stop(void); | 216 | void ieee80211s_stop(void); |
214 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 217 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
218 | ieee80211_rx_result | ||
219 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
220 | struct ieee80211_rx_status *rx_status); | ||
221 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | ||
222 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | ||
215 | 223 | ||
216 | /* Mesh paths */ | 224 | /* Mesh paths */ |
217 | int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); | 225 | int mesh_nexthop_lookup(struct sk_buff *skb, |
218 | void mesh_path_start_discovery(struct net_device *dev); | 226 | struct ieee80211_sub_if_data *sdata); |
219 | struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); | 227 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
220 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); | 228 | struct mesh_path *mesh_path_lookup(u8 *dst, |
229 | struct ieee80211_sub_if_data *sdata); | ||
230 | struct mesh_path *mpp_path_lookup(u8 *dst, | ||
231 | struct ieee80211_sub_if_data *sdata); | ||
232 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); | ||
233 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | ||
234 | struct ieee80211_sub_if_data *sdata); | ||
221 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 235 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
222 | void mesh_path_expire(struct net_device *dev); | 236 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
223 | void mesh_path_flush(struct net_device *dev); | 237 | void mesh_path_flush(struct ieee80211_sub_if_data *sdata); |
224 | void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 238 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
225 | size_t len); | 239 | struct ieee80211_mgmt *mgmt, size_t len); |
226 | int mesh_path_add(u8 *dst, struct net_device *dev); | 240 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); |
227 | /* Mesh plinks */ | 241 | /* Mesh plinks */ |
228 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | 242 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, |
229 | bool add); | 243 | struct ieee80211_sub_if_data *sdata, bool add); |
230 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, | 244 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
231 | struct net_device *dev); | ||
232 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 245 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
233 | void mesh_plink_broken(struct sta_info *sta); | 246 | void mesh_plink_broken(struct sta_info *sta); |
234 | void mesh_plink_deactivate(struct sta_info *sta); | 247 | void mesh_plink_deactivate(struct sta_info *sta); |
235 | int mesh_plink_open(struct sta_info *sta); | 248 | int mesh_plink_open(struct sta_info *sta); |
236 | int mesh_plink_close(struct sta_info *sta); | 249 | int mesh_plink_close(struct sta_info *sta); |
237 | void mesh_plink_block(struct sta_info *sta); | 250 | void mesh_plink_block(struct sta_info *sta); |
238 | void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 251 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, |
239 | size_t len, struct ieee80211_rx_status *rx_status); | 252 | struct ieee80211_mgmt *mgmt, size_t len, |
253 | struct ieee80211_rx_status *rx_status); | ||
240 | 254 | ||
241 | /* Private interfaces */ | 255 | /* Private interfaces */ |
242 | /* Mesh tables */ | 256 | /* Mesh tables */ |
243 | struct mesh_table *mesh_table_alloc(int size_order); | 257 | struct mesh_table *mesh_table_alloc(int size_order); |
244 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs); | 258 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs); |
245 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl); | 259 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl); |
246 | u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl); | 260 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, |
261 | struct mesh_table *tbl); | ||
247 | /* Mesh paths */ | 262 | /* Mesh paths */ |
248 | int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, | 263 | int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, |
249 | struct net_device *dev); | 264 | struct ieee80211_sub_if_data *sdata); |
250 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); | 265 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); |
251 | void mesh_path_flush_pending(struct mesh_path *mpath); | 266 | void mesh_path_flush_pending(struct mesh_path *mpath); |
252 | void mesh_path_tx_pending(struct mesh_path *mpath); | 267 | void mesh_path_tx_pending(struct mesh_path *mpath); |
253 | int mesh_pathtbl_init(void); | 268 | int mesh_pathtbl_init(void); |
254 | void mesh_pathtbl_unregister(void); | 269 | void mesh_pathtbl_unregister(void); |
255 | int mesh_path_del(u8 *addr, struct net_device *dev); | 270 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); |
256 | void mesh_path_timer(unsigned long data); | 271 | void mesh_path_timer(unsigned long data); |
257 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 272 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
258 | void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev); | 273 | void mesh_path_discard_frame(struct sk_buff *skb, |
274 | struct ieee80211_sub_if_data *sdata); | ||
259 | 275 | ||
260 | #ifdef CONFIG_MAC80211_MESH | 276 | #ifdef CONFIG_MAC80211_MESH |
261 | extern int mesh_allocated; | 277 | extern int mesh_allocated; |
262 | 278 | ||
263 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) | 279 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) |
264 | { | 280 | { |
265 | return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks - | 281 | return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - |
266 | atomic_read(&sdata->u.sta.mshstats.estab_plinks); | 282 | atomic_read(&sdata->u.mesh.mshstats.estab_plinks); |
267 | } | 283 | } |
268 | 284 | ||
269 | static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) | 285 | static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) |
@@ -281,8 +297,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
281 | for (i = 0; i <= x->hash_mask; i++) \ | 297 | for (i = 0; i <= x->hash_mask; i++) \ |
282 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) | 298 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) |
283 | 299 | ||
300 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); | ||
301 | |||
284 | #else | 302 | #else |
285 | #define mesh_allocated 0 | 303 | #define mesh_allocated 0 |
304 | static inline void | ||
305 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | ||
286 | #endif | 306 | #endif |
287 | 307 | ||
288 | #endif /* IEEE80211S_H */ | 308 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 08aca446ca01..501c7831adb4 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, |
@@ -82,9 +82,9 @@ enum mpath_frame_type { | |||
82 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | 82 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, |
83 | u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, | 83 | u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, |
84 | __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, | 84 | __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, |
85 | __le32 metric, __le32 preq_id, struct net_device *dev) | 85 | __le32 metric, __le32 preq_id, struct ieee80211_sub_if_data *sdata) |
86 | { | 86 | { |
87 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 87 | struct ieee80211_local *local = sdata->local; |
88 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 88 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
89 | struct ieee80211_mgmt *mgmt; | 89 | struct ieee80211_mgmt *mgmt; |
90 | u8 *pos; | 90 | u8 *pos; |
@@ -99,11 +99,11 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
99 | mgmt = (struct ieee80211_mgmt *) | 99 | mgmt = (struct ieee80211_mgmt *) |
100 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 100 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
101 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 101 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
102 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 102 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
103 | IEEE80211_STYPE_ACTION); | 103 | IEEE80211_STYPE_ACTION); |
104 | 104 | ||
105 | memcpy(mgmt->da, da, ETH_ALEN); | 105 | memcpy(mgmt->da, da, ETH_ALEN); |
106 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 106 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
107 | /* BSSID is left zeroed, wildcard value */ | 107 | /* BSSID is left zeroed, wildcard value */ |
108 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 108 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
109 | mgmt->u.action.u.mesh_action.action_code = action; | 109 | mgmt->u.action.u.mesh_action.action_code = action; |
@@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
149 | pos += ETH_ALEN; | 149 | pos += ETH_ALEN; |
150 | memcpy(pos, &dst_dsn, 4); | 150 | memcpy(pos, &dst_dsn, 4); |
151 | 151 | ||
152 | ieee80211_sta_tx(dev, skb, 0); | 152 | ieee80211_tx_skb(sdata, skb, 0); |
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
@@ -161,9 +161,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
161 | * @ra: node this frame is addressed to | 161 | * @ra: node this frame is addressed to |
162 | */ | 162 | */ |
163 | int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | 163 | int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, |
164 | struct net_device *dev) | 164 | struct ieee80211_sub_if_data *sdata) |
165 | { | 165 | { |
166 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 166 | struct ieee80211_local *local = sdata->local; |
167 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 167 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
168 | struct ieee80211_mgmt *mgmt; | 168 | struct ieee80211_mgmt *mgmt; |
169 | u8 *pos; | 169 | u8 *pos; |
@@ -178,11 +178,11 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | |||
178 | mgmt = (struct ieee80211_mgmt *) | 178 | mgmt = (struct ieee80211_mgmt *) |
179 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 179 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
180 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 180 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
181 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 181 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
182 | IEEE80211_STYPE_ACTION); | 182 | IEEE80211_STYPE_ACTION); |
183 | 183 | ||
184 | memcpy(mgmt->da, ra, ETH_ALEN); | 184 | memcpy(mgmt->da, ra, ETH_ALEN); |
185 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 185 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
186 | /* BSSID is left zeroed, wildcard value */ | 186 | /* BSSID is left zeroed, wildcard value */ |
187 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 187 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
188 | mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; | 188 | mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; |
@@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | |||
198 | pos += ETH_ALEN; | 198 | pos += ETH_ALEN; |
199 | memcpy(pos, &dst_dsn, 4); | 199 | memcpy(pos, &dst_dsn, 4); |
200 | 200 | ||
201 | ieee80211_sta_tx(dev, skb, 0); | 201 | ieee80211_tx_skb(sdata, skb, 0); |
202 | return 0; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
@@ -223,7 +223,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
223 | /* bitrate is in units of 100 Kbps, while we need rate in units of | 223 | /* bitrate is in units of 100 Kbps, while we need rate in units of |
224 | * 1Mbps. This will be corrected on tx_time computation. | 224 | * 1Mbps. This will be corrected on tx_time computation. |
225 | */ | 225 | */ |
226 | rate = sband->bitrates[sta->txrate_idx].bitrate; | 226 | rate = sband->bitrates[sta->last_txrate_idx].bitrate; |
227 | tx_time = (device_constant + 10 * test_frame_len / rate); | 227 | tx_time = (device_constant + 10 * test_frame_len / rate); |
228 | estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); | 228 | estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); |
229 | result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; | 229 | result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; |
@@ -233,7 +233,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
233 | /** | 233 | /** |
234 | * hwmp_route_info_get - Update routing info to originator and transmitter | 234 | * hwmp_route_info_get - Update routing info to originator and transmitter |
235 | * | 235 | * |
236 | * @dev: local mesh interface | 236 | * @sdata: local mesh subif |
237 | * @mgmt: mesh management frame | 237 | * @mgmt: mesh management frame |
238 | * @hwmp_ie: hwmp information element (PREP or PREQ) | 238 | * @hwmp_ie: hwmp information element (PREP or PREQ) |
239 | * | 239 | * |
@@ -246,11 +246,11 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
246 | * Notes: this function is the only place (besides user-provided info) where | 246 | * Notes: this function is the only place (besides user-provided info) where |
247 | * path routing information is updated. | 247 | * path routing information is updated. |
248 | */ | 248 | */ |
249 | static u32 hwmp_route_info_get(struct net_device *dev, | 249 | static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, |
250 | struct ieee80211_mgmt *mgmt, | 250 | struct ieee80211_mgmt *mgmt, |
251 | u8 *hwmp_ie) | 251 | u8 *hwmp_ie) |
252 | { | 252 | { |
253 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 253 | struct ieee80211_local *local = sdata->local; |
254 | struct mesh_path *mpath; | 254 | struct mesh_path *mpath; |
255 | struct sta_info *sta; | 255 | struct sta_info *sta; |
256 | bool fresh_info; | 256 | bool fresh_info; |
@@ -301,14 +301,14 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
301 | new_metric = MAX_METRIC; | 301 | new_metric = MAX_METRIC; |
302 | exp_time = TU_TO_EXP_TIME(orig_lifetime); | 302 | exp_time = TU_TO_EXP_TIME(orig_lifetime); |
303 | 303 | ||
304 | if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) { | 304 | if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { |
305 | /* This MP is the originator, we are not interested in this | 305 | /* This MP is the originator, we are not interested in this |
306 | * frame, except for updating transmitter's path info. | 306 | * frame, except for updating transmitter's path info. |
307 | */ | 307 | */ |
308 | process = false; | 308 | process = false; |
309 | fresh_info = false; | 309 | fresh_info = false; |
310 | } else { | 310 | } else { |
311 | mpath = mesh_path_lookup(orig_addr, dev); | 311 | mpath = mesh_path_lookup(orig_addr, sdata); |
312 | if (mpath) { | 312 | if (mpath) { |
313 | spin_lock_bh(&mpath->state_lock); | 313 | spin_lock_bh(&mpath->state_lock); |
314 | if (mpath->flags & MESH_PATH_FIXED) | 314 | if (mpath->flags & MESH_PATH_FIXED) |
@@ -324,8 +324,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
324 | } | 324 | } |
325 | } | 325 | } |
326 | } else { | 326 | } else { |
327 | mesh_path_add(orig_addr, dev); | 327 | mesh_path_add(orig_addr, sdata); |
328 | mpath = mesh_path_lookup(orig_addr, dev); | 328 | mpath = mesh_path_lookup(orig_addr, sdata); |
329 | if (!mpath) { | 329 | if (!mpath) { |
330 | rcu_read_unlock(); | 330 | rcu_read_unlock(); |
331 | return 0; | 331 | return 0; |
@@ -357,7 +357,7 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
357 | else { | 357 | else { |
358 | fresh_info = true; | 358 | fresh_info = true; |
359 | 359 | ||
360 | mpath = mesh_path_lookup(ta, dev); | 360 | mpath = mesh_path_lookup(ta, sdata); |
361 | if (mpath) { | 361 | if (mpath) { |
362 | spin_lock_bh(&mpath->state_lock); | 362 | spin_lock_bh(&mpath->state_lock); |
363 | if ((mpath->flags & MESH_PATH_FIXED) || | 363 | if ((mpath->flags & MESH_PATH_FIXED) || |
@@ -365,8 +365,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
365 | (last_hop_metric > mpath->metric))) | 365 | (last_hop_metric > mpath->metric))) |
366 | fresh_info = false; | 366 | fresh_info = false; |
367 | } else { | 367 | } else { |
368 | mesh_path_add(ta, dev); | 368 | mesh_path_add(ta, sdata); |
369 | mpath = mesh_path_lookup(ta, dev); | 369 | mpath = mesh_path_lookup(ta, sdata); |
370 | if (!mpath) { | 370 | if (!mpath) { |
371 | rcu_read_unlock(); | 371 | rcu_read_unlock(); |
372 | return 0; | 372 | return 0; |
@@ -392,11 +392,10 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
392 | return process ? new_metric : 0; | 392 | return process ? new_metric : 0; |
393 | } | 393 | } |
394 | 394 | ||
395 | static void hwmp_preq_frame_process(struct net_device *dev, | 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_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 398 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
399 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
400 | struct mesh_path *mpath; | 399 | struct mesh_path *mpath; |
401 | u8 *dst_addr, *orig_addr; | 400 | u8 *dst_addr, *orig_addr; |
402 | u8 dst_flags, ttl; | 401 | u8 dst_flags, ttl; |
@@ -411,19 +410,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
411 | orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); | 410 | orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); |
412 | dst_flags = PREQ_IE_DST_F(preq_elem); | 411 | dst_flags = PREQ_IE_DST_F(preq_elem); |
413 | 412 | ||
414 | if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) { | 413 | if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { |
415 | forward = false; | 414 | forward = false; |
416 | reply = true; | 415 | reply = true; |
417 | metric = 0; | 416 | metric = 0; |
418 | if (time_after(jiffies, ifsta->last_dsn_update + | 417 | if (time_after(jiffies, ifmsh->last_dsn_update + |
419 | net_traversal_jiffies(sdata)) || | 418 | net_traversal_jiffies(sdata)) || |
420 | time_before(jiffies, ifsta->last_dsn_update)) { | 419 | time_before(jiffies, ifmsh->last_dsn_update)) { |
421 | dst_dsn = ++ifsta->dsn; | 420 | dst_dsn = ++ifmsh->dsn; |
422 | ifsta->last_dsn_update = jiffies; | 421 | ifmsh->last_dsn_update = jiffies; |
423 | } | 422 | } |
424 | } else { | 423 | } else { |
425 | rcu_read_lock(); | 424 | rcu_read_lock(); |
426 | mpath = mesh_path_lookup(dst_addr, dev); | 425 | mpath = mesh_path_lookup(dst_addr, sdata); |
427 | if (mpath) { | 426 | if (mpath) { |
428 | if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || | 427 | if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || |
429 | DSN_LT(mpath->dsn, dst_dsn)) { | 428 | DSN_LT(mpath->dsn, dst_dsn)) { |
@@ -445,15 +444,15 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
445 | 444 | ||
446 | if (reply) { | 445 | if (reply) { |
447 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 446 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
448 | ttl = ifsta->mshcfg.dot11MeshTTL; | 447 | ttl = ifmsh->mshcfg.dot11MeshTTL; |
449 | if (ttl != 0) | 448 | if (ttl != 0) |
450 | mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, | 449 | mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, |
451 | cpu_to_le32(dst_dsn), 0, orig_addr, | 450 | cpu_to_le32(dst_dsn), 0, orig_addr, |
452 | cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, | 451 | cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, |
453 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 452 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
454 | 0, dev); | 453 | 0, sdata); |
455 | else | 454 | else |
456 | ifsta->mshstats.dropped_frames_ttl++; | 455 | ifmsh->mshstats.dropped_frames_ttl++; |
457 | } | 456 | } |
458 | 457 | ||
459 | if (forward) { | 458 | if (forward) { |
@@ -463,7 +462,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
463 | ttl = PREQ_IE_TTL(preq_elem); | 462 | ttl = PREQ_IE_TTL(preq_elem); |
464 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 463 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
465 | if (ttl <= 1) { | 464 | if (ttl <= 1) { |
466 | ifsta->mshstats.dropped_frames_ttl++; | 465 | ifmsh->mshstats.dropped_frames_ttl++; |
467 | return; | 466 | return; |
468 | } | 467 | } |
469 | --ttl; | 468 | --ttl; |
@@ -472,20 +471,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
472 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; | 471 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; |
473 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, | 472 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, |
474 | cpu_to_le32(orig_dsn), dst_flags, dst_addr, | 473 | cpu_to_le32(orig_dsn), dst_flags, dst_addr, |
475 | cpu_to_le32(dst_dsn), dev->broadcast, | 474 | cpu_to_le32(dst_dsn), sdata->dev->broadcast, |
476 | hopcount, ttl, cpu_to_le32(lifetime), | 475 | hopcount, ttl, cpu_to_le32(lifetime), |
477 | cpu_to_le32(metric), cpu_to_le32(preq_id), | 476 | cpu_to_le32(metric), cpu_to_le32(preq_id), |
478 | dev); | 477 | sdata); |
479 | ifsta->mshstats.fwded_frames++; | 478 | ifmsh->mshstats.fwded_frames++; |
480 | } | 479 | } |
481 | } | 480 | } |
482 | 481 | ||
483 | 482 | ||
484 | static void hwmp_prep_frame_process(struct net_device *dev, | 483 | static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, |
485 | struct ieee80211_mgmt *mgmt, | 484 | struct ieee80211_mgmt *mgmt, |
486 | u8 *prep_elem, u32 metric) | 485 | u8 *prep_elem, u32 metric) |
487 | { | 486 | { |
488 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
489 | struct mesh_path *mpath; | 487 | struct mesh_path *mpath; |
490 | u8 *dst_addr, *orig_addr; | 488 | u8 *dst_addr, *orig_addr; |
491 | u8 ttl, hopcount, flags; | 489 | u8 ttl, hopcount, flags; |
@@ -499,18 +497,18 @@ static void hwmp_prep_frame_process(struct net_device *dev, | |||
499 | * replies | 497 | * replies |
500 | */ | 498 | */ |
501 | dst_addr = PREP_IE_DST_ADDR(prep_elem); | 499 | dst_addr = PREP_IE_DST_ADDR(prep_elem); |
502 | if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) | 500 | if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) |
503 | /* destination, no forwarding required */ | 501 | /* destination, no forwarding required */ |
504 | return; | 502 | return; |
505 | 503 | ||
506 | ttl = PREP_IE_TTL(prep_elem); | 504 | ttl = PREP_IE_TTL(prep_elem); |
507 | if (ttl <= 1) { | 505 | if (ttl <= 1) { |
508 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 506 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
509 | return; | 507 | return; |
510 | } | 508 | } |
511 | 509 | ||
512 | rcu_read_lock(); | 510 | rcu_read_lock(); |
513 | mpath = mesh_path_lookup(dst_addr, dev); | 511 | mpath = mesh_path_lookup(dst_addr, sdata); |
514 | if (mpath) | 512 | if (mpath) |
515 | spin_lock_bh(&mpath->state_lock); | 513 | spin_lock_bh(&mpath->state_lock); |
516 | else | 514 | else |
@@ -519,7 +517,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, | |||
519 | spin_unlock_bh(&mpath->state_lock); | 517 | spin_unlock_bh(&mpath->state_lock); |
520 | goto fail; | 518 | goto fail; |
521 | } | 519 | } |
522 | memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); | 520 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); |
523 | spin_unlock_bh(&mpath->state_lock); | 521 | spin_unlock_bh(&mpath->state_lock); |
524 | --ttl; | 522 | --ttl; |
525 | flags = PREP_IE_FLAGS(prep_elem); | 523 | flags = PREP_IE_FLAGS(prep_elem); |
@@ -531,20 +529,20 @@ static void hwmp_prep_frame_process(struct net_device *dev, | |||
531 | 529 | ||
532 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, | 530 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, |
533 | cpu_to_le32(orig_dsn), 0, dst_addr, | 531 | cpu_to_le32(orig_dsn), 0, dst_addr, |
534 | cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl, | 532 | cpu_to_le32(dst_dsn), mpath->next_hop->sta.addr, hopcount, ttl, |
535 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 533 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
536 | 0, dev); | 534 | 0, sdata); |
537 | rcu_read_unlock(); | 535 | rcu_read_unlock(); |
538 | sdata->u.sta.mshstats.fwded_frames++; | 536 | sdata->u.mesh.mshstats.fwded_frames++; |
539 | return; | 537 | return; |
540 | 538 | ||
541 | fail: | 539 | fail: |
542 | rcu_read_unlock(); | 540 | rcu_read_unlock(); |
543 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 541 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
544 | return; | 542 | return; |
545 | } | 543 | } |
546 | 544 | ||
547 | static void hwmp_perr_frame_process(struct net_device *dev, | 545 | static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, |
548 | struct ieee80211_mgmt *mgmt, u8 *perr_elem) | 546 | struct ieee80211_mgmt *mgmt, u8 *perr_elem) |
549 | { | 547 | { |
550 | struct mesh_path *mpath; | 548 | struct mesh_path *mpath; |
@@ -555,18 +553,18 @@ static void hwmp_perr_frame_process(struct net_device *dev, | |||
555 | dst_addr = PERR_IE_DST_ADDR(perr_elem); | 553 | dst_addr = PERR_IE_DST_ADDR(perr_elem); |
556 | dst_dsn = PERR_IE_DST_DSN(perr_elem); | 554 | dst_dsn = PERR_IE_DST_DSN(perr_elem); |
557 | rcu_read_lock(); | 555 | rcu_read_lock(); |
558 | mpath = mesh_path_lookup(dst_addr, dev); | 556 | mpath = mesh_path_lookup(dst_addr, sdata); |
559 | if (mpath) { | 557 | if (mpath) { |
560 | spin_lock_bh(&mpath->state_lock); | 558 | spin_lock_bh(&mpath->state_lock); |
561 | if (mpath->flags & MESH_PATH_ACTIVE && | 559 | if (mpath->flags & MESH_PATH_ACTIVE && |
562 | memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 && | 560 | memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && |
563 | (!(mpath->flags & MESH_PATH_DSN_VALID) || | 561 | (!(mpath->flags & MESH_PATH_DSN_VALID) || |
564 | DSN_GT(dst_dsn, mpath->dsn))) { | 562 | DSN_GT(dst_dsn, mpath->dsn))) { |
565 | mpath->flags &= ~MESH_PATH_ACTIVE; | 563 | mpath->flags &= ~MESH_PATH_ACTIVE; |
566 | mpath->dsn = dst_dsn; | 564 | mpath->dsn = dst_dsn; |
567 | spin_unlock_bh(&mpath->state_lock); | 565 | spin_unlock_bh(&mpath->state_lock); |
568 | mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), | 566 | mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), |
569 | dev->broadcast, dev); | 567 | sdata->dev->broadcast, sdata); |
570 | } else | 568 | } else |
571 | spin_unlock_bh(&mpath->state_lock); | 569 | spin_unlock_bh(&mpath->state_lock); |
572 | } | 570 | } |
@@ -575,7 +573,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, | |||
575 | 573 | ||
576 | 574 | ||
577 | 575 | ||
578 | void mesh_rx_path_sel_frame(struct net_device *dev, | 576 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
579 | struct ieee80211_mgmt *mgmt, | 577 | struct ieee80211_mgmt *mgmt, |
580 | size_t len) | 578 | size_t len) |
581 | { | 579 | { |
@@ -583,6 +581,10 @@ void mesh_rx_path_sel_frame(struct net_device *dev, | |||
583 | size_t baselen; | 581 | size_t baselen; |
584 | u32 last_hop_metric; | 582 | u32 last_hop_metric; |
585 | 583 | ||
584 | /* need action_code */ | ||
585 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
586 | return; | ||
587 | |||
586 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; | 588 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; |
587 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, | 589 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, |
588 | len - baselen, &elems); | 590 | len - baselen, &elems); |
@@ -592,25 +594,25 @@ void mesh_rx_path_sel_frame(struct net_device *dev, | |||
592 | if (!elems.preq || elems.preq_len != 37) | 594 | if (!elems.preq || elems.preq_len != 37) |
593 | /* Right now we support just 1 destination and no AE */ | 595 | /* Right now we support just 1 destination and no AE */ |
594 | return; | 596 | return; |
595 | last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq); | 597 | last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq); |
596 | if (!last_hop_metric) | 598 | if (!last_hop_metric) |
597 | return; | 599 | return; |
598 | hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric); | 600 | hwmp_preq_frame_process(sdata, mgmt, elems.preq, last_hop_metric); |
599 | break; | 601 | break; |
600 | case MPATH_PREP: | 602 | case MPATH_PREP: |
601 | if (!elems.prep || elems.prep_len != 31) | 603 | if (!elems.prep || elems.prep_len != 31) |
602 | /* Right now we support no AE */ | 604 | /* Right now we support no AE */ |
603 | return; | 605 | return; |
604 | last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep); | 606 | last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep); |
605 | if (!last_hop_metric) | 607 | if (!last_hop_metric) |
606 | return; | 608 | return; |
607 | hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric); | 609 | hwmp_prep_frame_process(sdata, mgmt, elems.prep, last_hop_metric); |
608 | break; | 610 | break; |
609 | case MPATH_PERR: | 611 | case MPATH_PERR: |
610 | if (!elems.perr || elems.perr_len != 12) | 612 | if (!elems.perr || elems.perr_len != 12) |
611 | /* Right now we support only one destination per PERR */ | 613 | /* Right now we support only one destination per PERR */ |
612 | return; | 614 | return; |
613 | hwmp_perr_frame_process(dev, mgmt, elems.perr); | 615 | hwmp_perr_frame_process(sdata, mgmt, elems.perr); |
614 | default: | 616 | default: |
615 | return; | 617 | return; |
616 | } | 618 | } |
@@ -628,9 +630,8 @@ void mesh_rx_path_sel_frame(struct net_device *dev, | |||
628 | */ | 630 | */ |
629 | static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | 631 | static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) |
630 | { | 632 | { |
631 | struct ieee80211_sub_if_data *sdata = | 633 | struct ieee80211_sub_if_data *sdata = mpath->sdata; |
632 | IEEE80211_DEV_TO_SUB_IF(mpath->dev); | 634 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
633 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
634 | struct mesh_preq_queue *preq_node; | 635 | struct mesh_preq_queue *preq_node; |
635 | 636 | ||
636 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); | 637 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); |
@@ -639,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
639 | return; | 640 | return; |
640 | } | 641 | } |
641 | 642 | ||
642 | spin_lock(&ifsta->mesh_preq_queue_lock); | 643 | spin_lock(&ifmsh->mesh_preq_queue_lock); |
643 | if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { | 644 | if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { |
644 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 645 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
645 | kfree(preq_node); | 646 | kfree(preq_node); |
646 | if (printk_ratelimit()) | 647 | if (printk_ratelimit()) |
647 | printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); | 648 | printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); |
@@ -651,55 +652,53 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
651 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); | 652 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); |
652 | preq_node->flags = flags; | 653 | preq_node->flags = flags; |
653 | 654 | ||
654 | list_add_tail(&preq_node->list, &ifsta->preq_queue.list); | 655 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); |
655 | ++ifsta->preq_queue_len; | 656 | ++ifmsh->preq_queue_len; |
656 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 657 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
657 | 658 | ||
658 | 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))) |
659 | queue_work(sdata->local->hw.workqueue, &ifsta->work); | 660 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
660 | 661 | ||
661 | else if (time_before(jiffies, ifsta->last_preq)) { | 662 | else if (time_before(jiffies, ifmsh->last_preq)) { |
662 | /* 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 |
663 | * and jiffies wrapped around | 664 | * and jiffies wrapped around |
664 | */ | 665 | */ |
665 | ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; | 666 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; |
666 | queue_work(sdata->local->hw.workqueue, &ifsta->work); | 667 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
667 | } else | 668 | } else |
668 | mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + | 669 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + |
669 | min_preq_int_jiff(sdata)); | 670 | min_preq_int_jiff(sdata)); |
670 | } | 671 | } |
671 | 672 | ||
672 | /** | 673 | /** |
673 | * mesh_path_start_discovery - launch a path discovery from the PREQ queue | 674 | * mesh_path_start_discovery - launch a path discovery from the PREQ queue |
674 | * | 675 | * |
675 | * @dev: local mesh interface | 676 | * @sdata: local mesh subif |
676 | */ | 677 | */ |
677 | void mesh_path_start_discovery(struct net_device *dev) | 678 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) |
678 | { | 679 | { |
679 | struct ieee80211_sub_if_data *sdata = | 680 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
680 | IEEE80211_DEV_TO_SUB_IF(dev); | ||
681 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
682 | struct mesh_preq_queue *preq_node; | 681 | struct mesh_preq_queue *preq_node; |
683 | struct mesh_path *mpath; | 682 | struct mesh_path *mpath; |
684 | u8 ttl, dst_flags; | 683 | u8 ttl, dst_flags; |
685 | u32 lifetime; | 684 | u32 lifetime; |
686 | 685 | ||
687 | spin_lock(&ifsta->mesh_preq_queue_lock); | 686 | spin_lock(&ifmsh->mesh_preq_queue_lock); |
688 | if (!ifsta->preq_queue_len || | 687 | if (!ifmsh->preq_queue_len || |
689 | time_before(jiffies, ifsta->last_preq + | 688 | time_before(jiffies, ifmsh->last_preq + |
690 | min_preq_int_jiff(sdata))) { | 689 | min_preq_int_jiff(sdata))) { |
691 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 690 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
692 | return; | 691 | return; |
693 | } | 692 | } |
694 | 693 | ||
695 | preq_node = list_first_entry(&ifsta->preq_queue.list, | 694 | preq_node = list_first_entry(&ifmsh->preq_queue.list, |
696 | struct mesh_preq_queue, list); | 695 | struct mesh_preq_queue, list); |
697 | list_del(&preq_node->list); | 696 | list_del(&preq_node->list); |
698 | --ifsta->preq_queue_len; | 697 | --ifmsh->preq_queue_len; |
699 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 698 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
700 | 699 | ||
701 | rcu_read_lock(); | 700 | rcu_read_lock(); |
702 | mpath = mesh_path_lookup(preq_node->dst, dev); | 701 | mpath = mesh_path_lookup(preq_node->dst, sdata); |
703 | if (!mpath) | 702 | if (!mpath) |
704 | goto enddiscovery; | 703 | goto enddiscovery; |
705 | 704 | ||
@@ -721,18 +720,18 @@ void mesh_path_start_discovery(struct net_device *dev) | |||
721 | goto enddiscovery; | 720 | goto enddiscovery; |
722 | } | 721 | } |
723 | 722 | ||
724 | ifsta->last_preq = jiffies; | 723 | ifmsh->last_preq = jiffies; |
725 | 724 | ||
726 | if (time_after(jiffies, ifsta->last_dsn_update + | 725 | if (time_after(jiffies, ifmsh->last_dsn_update + |
727 | net_traversal_jiffies(sdata)) || | 726 | net_traversal_jiffies(sdata)) || |
728 | time_before(jiffies, ifsta->last_dsn_update)) { | 727 | time_before(jiffies, ifmsh->last_dsn_update)) { |
729 | ++ifsta->dsn; | 728 | ++ifmsh->dsn; |
730 | sdata->u.sta.last_dsn_update = jiffies; | 729 | sdata->u.mesh.last_dsn_update = jiffies; |
731 | } | 730 | } |
732 | lifetime = default_lifetime(sdata); | 731 | lifetime = default_lifetime(sdata); |
733 | ttl = sdata->u.sta.mshcfg.dot11MeshTTL; | 732 | ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
734 | if (ttl == 0) { | 733 | if (ttl == 0) { |
735 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 734 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
736 | spin_unlock_bh(&mpath->state_lock); | 735 | spin_unlock_bh(&mpath->state_lock); |
737 | goto enddiscovery; | 736 | goto enddiscovery; |
738 | } | 737 | } |
@@ -743,11 +742,11 @@ void mesh_path_start_discovery(struct net_device *dev) | |||
743 | dst_flags = MP_F_RF; | 742 | dst_flags = MP_F_RF; |
744 | 743 | ||
745 | spin_unlock_bh(&mpath->state_lock); | 744 | spin_unlock_bh(&mpath->state_lock); |
746 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr, | 745 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, |
747 | cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, | 746 | cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, |
748 | cpu_to_le32(mpath->dsn), dev->broadcast, 0, | 747 | cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, |
749 | ttl, cpu_to_le32(lifetime), 0, | 748 | ttl, cpu_to_le32(lifetime), 0, |
750 | cpu_to_le32(ifsta->preq_id++), dev); | 749 | cpu_to_le32(ifmsh->preq_id++), sdata); |
751 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); | 750 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); |
752 | 751 | ||
753 | enddiscovery: | 752 | enddiscovery: |
@@ -759,7 +758,7 @@ enddiscovery: | |||
759 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame | 758 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame |
760 | * | 759 | * |
761 | * @skb: 802.11 frame to be sent | 760 | * @skb: 802.11 frame to be sent |
762 | * @dev: network device the frame will be sent through | 761 | * @sdata: network subif the frame will be sent through |
763 | * @fwd_frame: true if this frame was originally from a different host | 762 | * @fwd_frame: true if this frame was originally from a different host |
764 | * | 763 | * |
765 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is | 764 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is |
@@ -767,9 +766,9 @@ enddiscovery: | |||
767 | * sent when the path is resolved. This means the caller must not free the skb | 766 | * sent when the path is resolved. This means the caller must not free the skb |
768 | * in this case. | 767 | * in this case. |
769 | */ | 768 | */ |
770 | int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | 769 | int mesh_nexthop_lookup(struct sk_buff *skb, |
770 | struct ieee80211_sub_if_data *sdata) | ||
771 | { | 771 | { |
772 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
773 | struct sk_buff *skb_to_free = NULL; | 772 | struct sk_buff *skb_to_free = NULL; |
774 | struct mesh_path *mpath; | 773 | struct mesh_path *mpath; |
775 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 774 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -777,14 +776,14 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | |||
777 | int err = 0; | 776 | int err = 0; |
778 | 777 | ||
779 | rcu_read_lock(); | 778 | rcu_read_lock(); |
780 | mpath = mesh_path_lookup(dst_addr, dev); | 779 | mpath = mesh_path_lookup(dst_addr, sdata); |
781 | 780 | ||
782 | if (!mpath) { | 781 | if (!mpath) { |
783 | mesh_path_add(dst_addr, dev); | 782 | mesh_path_add(dst_addr, sdata); |
784 | mpath = mesh_path_lookup(dst_addr, dev); | 783 | mpath = mesh_path_lookup(dst_addr, sdata); |
785 | if (!mpath) { | 784 | if (!mpath) { |
786 | dev_kfree_skb(skb); | 785 | dev_kfree_skb(skb); |
787 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 786 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
788 | err = -ENOSPC; | 787 | err = -ENOSPC; |
789 | goto endlookup; | 788 | goto endlookup; |
790 | } | 789 | } |
@@ -792,14 +791,15 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | |||
792 | 791 | ||
793 | if (mpath->flags & MESH_PATH_ACTIVE) { | 792 | if (mpath->flags & MESH_PATH_ACTIVE) { |
794 | if (time_after(jiffies, mpath->exp_time - | 793 | if (time_after(jiffies, mpath->exp_time - |
795 | msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) | 794 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) |
796 | && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) | 795 | && !memcmp(sdata->dev->dev_addr, hdr->addr4, |
796 | ETH_ALEN) | ||
797 | && !(mpath->flags & MESH_PATH_RESOLVING) | 797 | && !(mpath->flags & MESH_PATH_RESOLVING) |
798 | && !(mpath->flags & MESH_PATH_FIXED)) { | 798 | && !(mpath->flags & MESH_PATH_FIXED)) { |
799 | mesh_queue_preq(mpath, | 799 | mesh_queue_preq(mpath, |
800 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 800 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
801 | } | 801 | } |
802 | memcpy(hdr->addr1, mpath->next_hop->addr, | 802 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, |
803 | ETH_ALEN); | 803 | ETH_ALEN); |
804 | } else { | 804 | } else { |
805 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 805 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
@@ -815,7 +815,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | |||
815 | 815 | ||
816 | skb_queue_tail(&mpath->frame_queue, skb); | 816 | skb_queue_tail(&mpath->frame_queue, skb); |
817 | if (skb_to_free) | 817 | if (skb_to_free) |
818 | mesh_path_discard_frame(skb_to_free, dev); | 818 | mesh_path_discard_frame(skb_to_free, sdata); |
819 | err = -ENOENT; | 819 | err = -ENOENT; |
820 | } | 820 | } |
821 | 821 | ||
@@ -835,7 +835,7 @@ void mesh_path_timer(unsigned long data) | |||
835 | if (!mpath) | 835 | if (!mpath) |
836 | goto endmpathtimer; | 836 | goto endmpathtimer; |
837 | spin_lock_bh(&mpath->state_lock); | 837 | spin_lock_bh(&mpath->state_lock); |
838 | sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); | 838 | sdata = mpath->sdata; |
839 | if (mpath->flags & MESH_PATH_RESOLVED || | 839 | if (mpath->flags & MESH_PATH_RESOLVED || |
840 | (!(mpath->flags & MESH_PATH_RESOLVING))) | 840 | (!(mpath->flags & MESH_PATH_RESOLVING))) |
841 | mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); | 841 | mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 838ee60492ad..3c72557df45a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | #include <linux/etherdevice.h> | 10 | #include <linux/etherdevice.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/random.h> | 12 | #include <linux/random.h> |
14 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
15 | #include <linux/string.h> | 14 | #include <linux/string.h> |
@@ -37,6 +36,7 @@ struct mpath_node { | |||
37 | }; | 36 | }; |
38 | 37 | ||
39 | static struct mesh_table *mesh_paths; | 38 | static struct mesh_table *mesh_paths; |
39 | static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ | ||
40 | 40 | ||
41 | /* This lock will have the grow table function as writer and add / delete nodes | 41 | /* This lock will have the grow table function as writer and add / delete nodes |
42 | * as readers. When reading the table (i.e. doing lookups) we are well protected | 42 | * as readers. When reading the table (i.e. doing lookups) we are well protected |
@@ -62,13 +62,13 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
62 | /** | 62 | /** |
63 | * mesh_path_lookup - look up a path in the mesh path table | 63 | * mesh_path_lookup - look up a path in the mesh path table |
64 | * @dst: hardware address (ETH_ALEN length) of destination | 64 | * @dst: hardware address (ETH_ALEN length) of destination |
65 | * @dev: local interface | 65 | * @sdata: local subif |
66 | * | 66 | * |
67 | * Returns: pointer to the mesh path structure, or NULL if not found | 67 | * Returns: pointer to the mesh path structure, or NULL if not found |
68 | * | 68 | * |
69 | * Locking: must be called within a read rcu section. | 69 | * Locking: must be called within a read rcu section. |
70 | */ | 70 | */ |
71 | struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) | 71 | struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) |
72 | { | 72 | { |
73 | struct mesh_path *mpath; | 73 | struct mesh_path *mpath; |
74 | struct hlist_node *n; | 74 | struct hlist_node *n; |
@@ -78,10 +78,10 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) | |||
78 | 78 | ||
79 | tbl = rcu_dereference(mesh_paths); | 79 | tbl = rcu_dereference(mesh_paths); |
80 | 80 | ||
81 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)]; | 81 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; |
82 | hlist_for_each_entry_rcu(node, n, bucket, list) { | 82 | hlist_for_each_entry_rcu(node, n, bucket, list) { |
83 | mpath = node->mpath; | 83 | mpath = node->mpath; |
84 | if (mpath->dev == dev && | 84 | if (mpath->sdata == sdata && |
85 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | 85 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { |
86 | if (MPATH_EXPIRED(mpath)) { | 86 | if (MPATH_EXPIRED(mpath)) { |
87 | spin_lock_bh(&mpath->state_lock); | 87 | spin_lock_bh(&mpath->state_lock); |
@@ -95,16 +95,44 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) | |||
95 | return NULL; | 95 | return NULL; |
96 | } | 96 | } |
97 | 97 | ||
98 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | ||
99 | { | ||
100 | struct mesh_path *mpath; | ||
101 | struct hlist_node *n; | ||
102 | struct hlist_head *bucket; | ||
103 | struct mesh_table *tbl; | ||
104 | struct mpath_node *node; | ||
105 | |||
106 | tbl = rcu_dereference(mpp_paths); | ||
107 | |||
108 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; | ||
109 | hlist_for_each_entry_rcu(node, n, bucket, list) { | ||
110 | mpath = node->mpath; | ||
111 | if (mpath->sdata == sdata && | ||
112 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | ||
113 | if (MPATH_EXPIRED(mpath)) { | ||
114 | spin_lock_bh(&mpath->state_lock); | ||
115 | if (MPATH_EXPIRED(mpath)) | ||
116 | mpath->flags &= ~MESH_PATH_ACTIVE; | ||
117 | spin_unlock_bh(&mpath->state_lock); | ||
118 | } | ||
119 | return mpath; | ||
120 | } | ||
121 | } | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | |||
98 | /** | 126 | /** |
99 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index | 127 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index |
100 | * @idx: index | 128 | * @idx: index |
101 | * @dev: local interface, or NULL for all entries | 129 | * @sdata: local subif, or NULL for all entries |
102 | * | 130 | * |
103 | * Returns: pointer to the mesh path structure, or NULL if not found. | 131 | * Returns: pointer to the mesh path structure, or NULL if not found. |
104 | * | 132 | * |
105 | * Locking: must be called within a read rcu section. | 133 | * Locking: must be called within a read rcu section. |
106 | */ | 134 | */ |
107 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) | 135 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) |
108 | { | 136 | { |
109 | struct mpath_node *node; | 137 | struct mpath_node *node; |
110 | struct hlist_node *p; | 138 | struct hlist_node *p; |
@@ -112,7 +140,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) | |||
112 | int j = 0; | 140 | int j = 0; |
113 | 141 | ||
114 | for_each_mesh_entry(mesh_paths, p, node, i) { | 142 | for_each_mesh_entry(mesh_paths, p, node, i) { |
115 | if (dev && node->mpath->dev != dev) | 143 | if (sdata && node->mpath->sdata != sdata) |
116 | continue; | 144 | continue; |
117 | if (j++ == idx) { | 145 | if (j++ == idx) { |
118 | if (MPATH_EXPIRED(node->mpath)) { | 146 | if (MPATH_EXPIRED(node->mpath)) { |
@@ -131,15 +159,14 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) | |||
131 | /** | 159 | /** |
132 | * mesh_path_add - allocate and add a new path to the mesh path table | 160 | * mesh_path_add - allocate and add a new path to the mesh path table |
133 | * @addr: destination address of the path (ETH_ALEN length) | 161 | * @addr: destination address of the path (ETH_ALEN length) |
134 | * @dev: local interface | 162 | * @sdata: local subif |
135 | * | 163 | * |
136 | * Returns: 0 on sucess | 164 | * Returns: 0 on sucess |
137 | * | 165 | * |
138 | * State: the initial state of the new path is set to 0 | 166 | * State: the initial state of the new path is set to 0 |
139 | */ | 167 | */ |
140 | int mesh_path_add(u8 *dst, struct net_device *dev) | 168 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) |
141 | { | 169 | { |
142 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
143 | struct mesh_path *mpath, *new_mpath; | 170 | struct mesh_path *mpath, *new_mpath; |
144 | struct mpath_node *node, *new_node; | 171 | struct mpath_node *node, *new_node; |
145 | struct hlist_head *bucket; | 172 | struct hlist_head *bucket; |
@@ -148,14 +175,14 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
148 | int err = 0; | 175 | int err = 0; |
149 | u32 hash_idx; | 176 | u32 hash_idx; |
150 | 177 | ||
151 | if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0) | 178 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) |
152 | /* never add ourselves as neighbours */ | 179 | /* never add ourselves as neighbours */ |
153 | return -ENOTSUPP; | 180 | return -ENOTSUPP; |
154 | 181 | ||
155 | if (is_multicast_ether_addr(dst)) | 182 | if (is_multicast_ether_addr(dst)) |
156 | return -ENOTSUPP; | 183 | return -ENOTSUPP; |
157 | 184 | ||
158 | if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) | 185 | if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) |
159 | return -ENOSPC; | 186 | return -ENOSPC; |
160 | 187 | ||
161 | err = -ENOMEM; | 188 | err = -ENOMEM; |
@@ -169,7 +196,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
169 | 196 | ||
170 | read_lock(&pathtbl_resize_lock); | 197 | read_lock(&pathtbl_resize_lock); |
171 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 198 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
172 | new_mpath->dev = dev; | 199 | new_mpath->sdata = sdata; |
173 | new_mpath->flags = 0; | 200 | new_mpath->flags = 0; |
174 | skb_queue_head_init(&new_mpath->frame_queue); | 201 | skb_queue_head_init(&new_mpath->frame_queue); |
175 | new_node->mpath = new_mpath; | 202 | new_node->mpath = new_mpath; |
@@ -179,7 +206,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
179 | spin_lock_init(&new_mpath->state_lock); | 206 | spin_lock_init(&new_mpath->state_lock); |
180 | init_timer(&new_mpath->timer); | 207 | init_timer(&new_mpath->timer); |
181 | 208 | ||
182 | hash_idx = mesh_table_hash(dst, dev, mesh_paths); | 209 | hash_idx = mesh_table_hash(dst, sdata, mesh_paths); |
183 | bucket = &mesh_paths->hash_buckets[hash_idx]; | 210 | bucket = &mesh_paths->hash_buckets[hash_idx]; |
184 | 211 | ||
185 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 212 | spin_lock(&mesh_paths->hashwlock[hash_idx]); |
@@ -187,7 +214,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
187 | err = -EEXIST; | 214 | err = -EEXIST; |
188 | hlist_for_each_entry(node, n, bucket, list) { | 215 | hlist_for_each_entry(node, n, bucket, list) { |
189 | mpath = node->mpath; | 216 | mpath = node->mpath; |
190 | if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | 217 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) |
191 | goto err_exists; | 218 | goto err_exists; |
192 | } | 219 | } |
193 | 220 | ||
@@ -223,7 +250,92 @@ err_exists: | |||
223 | err_node_alloc: | 250 | err_node_alloc: |
224 | kfree(new_mpath); | 251 | kfree(new_mpath); |
225 | err_path_alloc: | 252 | err_path_alloc: |
226 | atomic_dec(&sdata->u.sta.mpaths); | 253 | atomic_dec(&sdata->u.mesh.mpaths); |
254 | return err; | ||
255 | } | ||
256 | |||
257 | |||
258 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | ||
259 | { | ||
260 | struct mesh_path *mpath, *new_mpath; | ||
261 | struct mpath_node *node, *new_node; | ||
262 | struct hlist_head *bucket; | ||
263 | struct hlist_node *n; | ||
264 | int grow = 0; | ||
265 | int err = 0; | ||
266 | u32 hash_idx; | ||
267 | |||
268 | |||
269 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | ||
270 | /* never add ourselves as neighbours */ | ||
271 | return -ENOTSUPP; | ||
272 | |||
273 | if (is_multicast_ether_addr(dst)) | ||
274 | return -ENOTSUPP; | ||
275 | |||
276 | err = -ENOMEM; | ||
277 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); | ||
278 | if (!new_mpath) | ||
279 | goto err_path_alloc; | ||
280 | |||
281 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); | ||
282 | if (!new_node) | ||
283 | goto err_node_alloc; | ||
284 | |||
285 | read_lock(&pathtbl_resize_lock); | ||
286 | memcpy(new_mpath->dst, dst, ETH_ALEN); | ||
287 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); | ||
288 | new_mpath->sdata = sdata; | ||
289 | new_mpath->flags = 0; | ||
290 | skb_queue_head_init(&new_mpath->frame_queue); | ||
291 | new_node->mpath = new_mpath; | ||
292 | new_mpath->exp_time = jiffies; | ||
293 | spin_lock_init(&new_mpath->state_lock); | ||
294 | |||
295 | hash_idx = mesh_table_hash(dst, sdata, mpp_paths); | ||
296 | bucket = &mpp_paths->hash_buckets[hash_idx]; | ||
297 | |||
298 | spin_lock(&mpp_paths->hashwlock[hash_idx]); | ||
299 | |||
300 | err = -EEXIST; | ||
301 | hlist_for_each_entry(node, n, bucket, list) { | ||
302 | mpath = node->mpath; | ||
303 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | ||
304 | goto err_exists; | ||
305 | } | ||
306 | |||
307 | hlist_add_head_rcu(&new_node->list, bucket); | ||
308 | if (atomic_inc_return(&mpp_paths->entries) >= | ||
309 | mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) | ||
310 | grow = 1; | ||
311 | |||
312 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
313 | read_unlock(&pathtbl_resize_lock); | ||
314 | if (grow) { | ||
315 | struct mesh_table *oldtbl, *newtbl; | ||
316 | |||
317 | write_lock(&pathtbl_resize_lock); | ||
318 | oldtbl = mpp_paths; | ||
319 | newtbl = mesh_table_grow(mpp_paths); | ||
320 | if (!newtbl) { | ||
321 | write_unlock(&pathtbl_resize_lock); | ||
322 | return 0; | ||
323 | } | ||
324 | rcu_assign_pointer(mpp_paths, newtbl); | ||
325 | write_unlock(&pathtbl_resize_lock); | ||
326 | |||
327 | synchronize_rcu(); | ||
328 | mesh_table_free(oldtbl, false); | ||
329 | } | ||
330 | return 0; | ||
331 | |||
332 | err_exists: | ||
333 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
334 | read_unlock(&pathtbl_resize_lock); | ||
335 | kfree(new_node); | ||
336 | err_node_alloc: | ||
337 | kfree(new_mpath); | ||
338 | err_path_alloc: | ||
227 | return err; | 339 | return err; |
228 | } | 340 | } |
229 | 341 | ||
@@ -241,7 +353,7 @@ void mesh_plink_broken(struct sta_info *sta) | |||
241 | struct mesh_path *mpath; | 353 | struct mesh_path *mpath; |
242 | struct mpath_node *node; | 354 | struct mpath_node *node; |
243 | struct hlist_node *p; | 355 | struct hlist_node *p; |
244 | struct net_device *dev = sta->sdata->dev; | 356 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
245 | int i; | 357 | int i; |
246 | 358 | ||
247 | rcu_read_lock(); | 359 | rcu_read_lock(); |
@@ -256,7 +368,7 @@ void mesh_plink_broken(struct sta_info *sta) | |||
256 | spin_unlock_bh(&mpath->state_lock); | 368 | spin_unlock_bh(&mpath->state_lock); |
257 | mesh_path_error_tx(mpath->dst, | 369 | mesh_path_error_tx(mpath->dst, |
258 | cpu_to_le32(mpath->dsn), | 370 | cpu_to_le32(mpath->dsn), |
259 | dev->broadcast, dev); | 371 | sdata->dev->broadcast, sdata); |
260 | } else | 372 | } else |
261 | spin_unlock_bh(&mpath->state_lock); | 373 | spin_unlock_bh(&mpath->state_lock); |
262 | } | 374 | } |
@@ -284,11 +396,11 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) | |||
284 | for_each_mesh_entry(mesh_paths, p, node, i) { | 396 | for_each_mesh_entry(mesh_paths, p, node, i) { |
285 | mpath = node->mpath; | 397 | mpath = node->mpath; |
286 | if (mpath->next_hop == sta) | 398 | if (mpath->next_hop == sta) |
287 | mesh_path_del(mpath->dst, mpath->dev); | 399 | mesh_path_del(mpath->dst, mpath->sdata); |
288 | } | 400 | } |
289 | } | 401 | } |
290 | 402 | ||
291 | void mesh_path_flush(struct net_device *dev) | 403 | void mesh_path_flush(struct ieee80211_sub_if_data *sdata) |
292 | { | 404 | { |
293 | struct mesh_path *mpath; | 405 | struct mesh_path *mpath; |
294 | struct mpath_node *node; | 406 | struct mpath_node *node; |
@@ -297,19 +409,18 @@ void mesh_path_flush(struct net_device *dev) | |||
297 | 409 | ||
298 | for_each_mesh_entry(mesh_paths, p, node, i) { | 410 | for_each_mesh_entry(mesh_paths, p, node, i) { |
299 | mpath = node->mpath; | 411 | mpath = node->mpath; |
300 | if (mpath->dev == dev) | 412 | if (mpath->sdata == sdata) |
301 | mesh_path_del(mpath->dst, mpath->dev); | 413 | mesh_path_del(mpath->dst, mpath->sdata); |
302 | } | 414 | } |
303 | } | 415 | } |
304 | 416 | ||
305 | static void mesh_path_node_reclaim(struct rcu_head *rp) | 417 | static void mesh_path_node_reclaim(struct rcu_head *rp) |
306 | { | 418 | { |
307 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | 419 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); |
308 | struct ieee80211_sub_if_data *sdata = | 420 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; |
309 | IEEE80211_DEV_TO_SUB_IF(node->mpath->dev); | ||
310 | 421 | ||
311 | del_timer_sync(&node->mpath->timer); | 422 | del_timer_sync(&node->mpath->timer); |
312 | atomic_dec(&sdata->u.sta.mpaths); | 423 | atomic_dec(&sdata->u.mesh.mpaths); |
313 | kfree(node->mpath); | 424 | kfree(node->mpath); |
314 | kfree(node); | 425 | kfree(node); |
315 | } | 426 | } |
@@ -318,11 +429,11 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) | |||
318 | * mesh_path_del - delete a mesh path from the table | 429 | * mesh_path_del - delete a mesh path from the table |
319 | * | 430 | * |
320 | * @addr: dst address (ETH_ALEN length) | 431 | * @addr: dst address (ETH_ALEN length) |
321 | * @dev: local interface | 432 | * @sdata: local subif |
322 | * | 433 | * |
323 | * Returns: 0 if succesful | 434 | * Returns: 0 if succesful |
324 | */ | 435 | */ |
325 | int mesh_path_del(u8 *addr, struct net_device *dev) | 436 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) |
326 | { | 437 | { |
327 | struct mesh_path *mpath; | 438 | struct mesh_path *mpath; |
328 | struct mpath_node *node; | 439 | struct mpath_node *node; |
@@ -332,13 +443,13 @@ int mesh_path_del(u8 *addr, struct net_device *dev) | |||
332 | int err = 0; | 443 | int err = 0; |
333 | 444 | ||
334 | read_lock(&pathtbl_resize_lock); | 445 | read_lock(&pathtbl_resize_lock); |
335 | hash_idx = mesh_table_hash(addr, dev, mesh_paths); | 446 | hash_idx = mesh_table_hash(addr, sdata, mesh_paths); |
336 | bucket = &mesh_paths->hash_buckets[hash_idx]; | 447 | bucket = &mesh_paths->hash_buckets[hash_idx]; |
337 | 448 | ||
338 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 449 | spin_lock(&mesh_paths->hashwlock[hash_idx]); |
339 | hlist_for_each_entry(node, n, bucket, list) { | 450 | hlist_for_each_entry(node, n, bucket, list) { |
340 | mpath = node->mpath; | 451 | mpath = node->mpath; |
341 | if (mpath->dev == dev && | 452 | if (mpath->sdata == sdata && |
342 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { | 453 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { |
343 | spin_lock_bh(&mpath->state_lock); | 454 | spin_lock_bh(&mpath->state_lock); |
344 | mpath->flags |= MESH_PATH_RESOLVING; | 455 | mpath->flags |= MESH_PATH_RESOLVING; |
@@ -378,33 +489,33 @@ void mesh_path_tx_pending(struct mesh_path *mpath) | |||
378 | * mesh_path_discard_frame - discard a frame whose path could not be resolved | 489 | * mesh_path_discard_frame - discard a frame whose path could not be resolved |
379 | * | 490 | * |
380 | * @skb: frame to discard | 491 | * @skb: frame to discard |
381 | * @dev: network device the frame was to be sent through | 492 | * @sdata: network subif the frame was to be sent through |
382 | * | 493 | * |
383 | * If the frame was beign forwarded from another MP, a PERR frame will be sent | 494 | * If the frame was beign forwarded from another MP, a PERR frame will be sent |
384 | * to the precursor. | 495 | * to the precursor. |
385 | * | 496 | * |
386 | * Locking: the function must me called within a rcu_read_lock region | 497 | * Locking: the function must me called within a rcu_read_lock region |
387 | */ | 498 | */ |
388 | void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) | 499 | void mesh_path_discard_frame(struct sk_buff *skb, |
500 | struct ieee80211_sub_if_data *sdata) | ||
389 | { | 501 | { |
390 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
391 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 502 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
392 | struct mesh_path *mpath; | 503 | struct mesh_path *mpath; |
393 | u32 dsn = 0; | 504 | u32 dsn = 0; |
394 | 505 | ||
395 | if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { | 506 | if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { |
396 | u8 *ra, *da; | 507 | u8 *ra, *da; |
397 | 508 | ||
398 | da = hdr->addr3; | 509 | da = hdr->addr3; |
399 | ra = hdr->addr2; | 510 | ra = hdr->addr2; |
400 | mpath = mesh_path_lookup(da, dev); | 511 | mpath = mesh_path_lookup(da, sdata); |
401 | if (mpath) | 512 | if (mpath) |
402 | dsn = ++mpath->dsn; | 513 | dsn = ++mpath->dsn; |
403 | mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev); | 514 | mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, sdata); |
404 | } | 515 | } |
405 | 516 | ||
406 | kfree_skb(skb); | 517 | kfree_skb(skb); |
407 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 518 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
408 | } | 519 | } |
409 | 520 | ||
410 | /** | 521 | /** |
@@ -416,14 +527,11 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) | |||
416 | */ | 527 | */ |
417 | void mesh_path_flush_pending(struct mesh_path *mpath) | 528 | void mesh_path_flush_pending(struct mesh_path *mpath) |
418 | { | 529 | { |
419 | struct ieee80211_sub_if_data *sdata; | ||
420 | struct sk_buff *skb; | 530 | struct sk_buff *skb; |
421 | 531 | ||
422 | sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); | ||
423 | |||
424 | while ((skb = skb_dequeue(&mpath->frame_queue)) && | 532 | while ((skb = skb_dequeue(&mpath->frame_queue)) && |
425 | (mpath->flags & MESH_PATH_ACTIVE)) | 533 | (mpath->flags & MESH_PATH_ACTIVE)) |
426 | mesh_path_discard_frame(skb, mpath->dev); | 534 | mesh_path_discard_frame(skb, mpath->sdata); |
427 | } | 535 | } |
428 | 536 | ||
429 | /** | 537 | /** |
@@ -472,7 +580,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
472 | node = hlist_entry(p, struct mpath_node, list); | 580 | node = hlist_entry(p, struct mpath_node, list); |
473 | mpath = node->mpath; | 581 | mpath = node->mpath; |
474 | new_node->mpath = mpath; | 582 | new_node->mpath = mpath; |
475 | hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); | 583 | hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl); |
476 | hlist_add_head(&new_node->list, | 584 | hlist_add_head(&new_node->list, |
477 | &newtbl->hash_buckets[hash_idx]); | 585 | &newtbl->hash_buckets[hash_idx]); |
478 | return 0; | 586 | return 0; |
@@ -481,15 +589,25 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
481 | int mesh_pathtbl_init(void) | 589 | int mesh_pathtbl_init(void) |
482 | { | 590 | { |
483 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | 591 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); |
592 | if (!mesh_paths) | ||
593 | return -ENOMEM; | ||
484 | mesh_paths->free_node = &mesh_path_node_free; | 594 | mesh_paths->free_node = &mesh_path_node_free; |
485 | mesh_paths->copy_node = &mesh_path_node_copy; | 595 | mesh_paths->copy_node = &mesh_path_node_copy; |
486 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; | 596 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; |
487 | if (!mesh_paths) | 597 | |
598 | mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | ||
599 | if (!mpp_paths) { | ||
600 | mesh_table_free(mesh_paths, true); | ||
488 | return -ENOMEM; | 601 | return -ENOMEM; |
602 | } | ||
603 | mpp_paths->free_node = &mesh_path_node_free; | ||
604 | mpp_paths->copy_node = &mesh_path_node_copy; | ||
605 | mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; | ||
606 | |||
489 | return 0; | 607 | return 0; |
490 | } | 608 | } |
491 | 609 | ||
492 | void mesh_path_expire(struct net_device *dev) | 610 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata) |
493 | { | 611 | { |
494 | struct mesh_path *mpath; | 612 | struct mesh_path *mpath; |
495 | struct mpath_node *node; | 613 | struct mpath_node *node; |
@@ -498,7 +616,7 @@ void mesh_path_expire(struct net_device *dev) | |||
498 | 616 | ||
499 | read_lock(&pathtbl_resize_lock); | 617 | read_lock(&pathtbl_resize_lock); |
500 | for_each_mesh_entry(mesh_paths, p, node, i) { | 618 | for_each_mesh_entry(mesh_paths, p, node, i) { |
501 | if (node->mpath->dev != dev) | 619 | if (node->mpath->sdata != sdata) |
502 | continue; | 620 | continue; |
503 | mpath = node->mpath; | 621 | mpath = node->mpath; |
504 | spin_lock_bh(&mpath->state_lock); | 622 | spin_lock_bh(&mpath->state_lock); |
@@ -507,7 +625,7 @@ void mesh_path_expire(struct net_device *dev) | |||
507 | time_after(jiffies, | 625 | time_after(jiffies, |
508 | mpath->exp_time + MESH_PATH_EXPIRE)) { | 626 | mpath->exp_time + MESH_PATH_EXPIRE)) { |
509 | spin_unlock_bh(&mpath->state_lock); | 627 | spin_unlock_bh(&mpath->state_lock); |
510 | mesh_path_del(mpath->dst, mpath->dev); | 628 | mesh_path_del(mpath->dst, mpath->sdata); |
511 | } else | 629 | } else |
512 | spin_unlock_bh(&mpath->state_lock); | 630 | spin_unlock_bh(&mpath->state_lock); |
513 | } | 631 | } |
@@ -517,4 +635,5 @@ void mesh_path_expire(struct net_device *dev) | |||
517 | void mesh_pathtbl_unregister(void) | 635 | void mesh_pathtbl_unregister(void) |
518 | { | 636 | { |
519 | mesh_table_free(mesh_paths, true); | 637 | mesh_table_free(mesh_paths, true); |
638 | mesh_table_free(mpp_paths, true); | ||
520 | } | 639 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9efeb1f07025..faac101c0f85 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 | ||
@@ -106,7 +106,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
106 | return NULL; | 106 | return NULL; |
107 | 107 | ||
108 | sta->flags = WLAN_STA_AUTHORIZED; | 108 | sta->flags = WLAN_STA_AUTHORIZED; |
109 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 109 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
110 | 110 | ||
111 | return sta; | 111 | return sta; |
112 | } | 112 | } |
@@ -144,10 +144,10 @@ void mesh_plink_deactivate(struct sta_info *sta) | |||
144 | spin_unlock_bh(&sta->lock); | 144 | spin_unlock_bh(&sta->lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int mesh_plink_frame_tx(struct net_device *dev, | 147 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
148 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, | 148 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, |
149 | __le16 reason) { | 149 | __le16 reason) { |
150 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 150 | struct ieee80211_local *local = sdata->local; |
151 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 151 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
152 | struct ieee80211_mgmt *mgmt; | 152 | struct ieee80211_mgmt *mgmt; |
153 | bool include_plid = false; | 153 | bool include_plid = false; |
@@ -163,10 +163,10 @@ static int mesh_plink_frame_tx(struct net_device *dev, | |||
163 | mgmt = (struct ieee80211_mgmt *) | 163 | mgmt = (struct ieee80211_mgmt *) |
164 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); | 164 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); |
165 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); | 165 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); |
166 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 166 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
167 | IEEE80211_STYPE_ACTION); | 167 | IEEE80211_STYPE_ACTION); |
168 | memcpy(mgmt->da, da, ETH_ALEN); | 168 | memcpy(mgmt->da, da, ETH_ALEN); |
169 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 169 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
170 | /* BSSID is left zeroed, wildcard value */ | 170 | /* BSSID is left zeroed, wildcard value */ |
171 | mgmt->u.action.category = PLINK_CATEGORY; | 171 | mgmt->u.action.category = PLINK_CATEGORY; |
172 | mgmt->u.action.u.plink_action.action_code = action; | 172 | mgmt->u.action.u.plink_action.action_code = action; |
@@ -180,7 +180,7 @@ static int mesh_plink_frame_tx(struct net_device *dev, | |||
180 | /* two-byte status code followed by two-byte AID */ | 180 | /* two-byte status code followed by two-byte AID */ |
181 | memset(pos, 0, 4); | 181 | memset(pos, 0, 4); |
182 | } | 182 | } |
183 | mesh_mgmt_ies_add(skb, dev); | 183 | mesh_mgmt_ies_add(skb, sdata); |
184 | } | 184 | } |
185 | 185 | ||
186 | /* Add Peer Link Management element */ | 186 | /* Add Peer Link Management element */ |
@@ -217,15 +217,14 @@ static int mesh_plink_frame_tx(struct net_device *dev, | |||
217 | memcpy(pos, &reason, 2); | 217 | memcpy(pos, &reason, 2); |
218 | } | 218 | } |
219 | 219 | ||
220 | ieee80211_sta_tx(dev, skb, 0); | 220 | ieee80211_tx_skb(sdata, skb, 0); |
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | 223 | ||
224 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | 224 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, |
225 | bool peer_accepting_plinks) | 225 | bool peer_accepting_plinks) |
226 | { | 226 | { |
227 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 227 | struct ieee80211_local *local = sdata->local; |
228 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
229 | struct sta_info *sta; | 228 | struct sta_info *sta; |
230 | 229 | ||
231 | rcu_read_lock(); | 230 | rcu_read_lock(); |
@@ -244,10 +243,10 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | |||
244 | } | 243 | } |
245 | 244 | ||
246 | sta->last_rx = jiffies; | 245 | sta->last_rx = jiffies; |
247 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 246 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
248 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && | 247 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && |
249 | sdata->u.sta.accepting_plinks && | 248 | sdata->u.mesh.accepting_plinks && |
250 | sdata->u.sta.mshcfg.auto_open_plinks) | 249 | sdata->u.mesh.mshcfg.auto_open_plinks) |
251 | mesh_plink_open(sta); | 250 | mesh_plink_open(sta); |
252 | 251 | ||
253 | rcu_read_unlock(); | 252 | rcu_read_unlock(); |
@@ -257,7 +256,6 @@ static void mesh_plink_timer(unsigned long data) | |||
257 | { | 256 | { |
258 | struct sta_info *sta; | 257 | struct sta_info *sta; |
259 | __le16 llid, plid, reason; | 258 | __le16 llid, plid, reason; |
260 | struct net_device *dev = NULL; | ||
261 | struct ieee80211_sub_if_data *sdata; | 259 | struct ieee80211_sub_if_data *sdata; |
262 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 260 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
263 | DECLARE_MAC_BUF(mac); | 261 | DECLARE_MAC_BUF(mac); |
@@ -277,12 +275,11 @@ static void mesh_plink_timer(unsigned long data) | |||
277 | return; | 275 | return; |
278 | } | 276 | } |
279 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", | 277 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", |
280 | print_mac(mac, sta->addr), sta->plink_state); | 278 | print_mac(mac, sta->sta.addr), sta->plink_state); |
281 | reason = 0; | 279 | reason = 0; |
282 | llid = sta->llid; | 280 | llid = sta->llid; |
283 | plid = sta->plid; | 281 | plid = sta->plid; |
284 | sdata = sta->sdata; | 282 | sdata = sta->sdata; |
285 | dev = sdata->dev; | ||
286 | 283 | ||
287 | switch (sta->plink_state) { | 284 | switch (sta->plink_state) { |
288 | case PLINK_OPN_RCVD: | 285 | case PLINK_OPN_RCVD: |
@@ -291,7 +288,7 @@ static void mesh_plink_timer(unsigned long data) | |||
291 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { | 288 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { |
292 | u32 rand; | 289 | u32 rand; |
293 | mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n", | 290 | mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n", |
294 | print_mac(mac, sta->addr), | 291 | print_mac(mac, sta->sta.addr), |
295 | sta->plink_retries, sta->plink_timeout); | 292 | sta->plink_retries, sta->plink_timeout); |
296 | get_random_bytes(&rand, sizeof(u32)); | 293 | get_random_bytes(&rand, sizeof(u32)); |
297 | sta->plink_timeout = sta->plink_timeout + | 294 | sta->plink_timeout = sta->plink_timeout + |
@@ -299,7 +296,7 @@ static void mesh_plink_timer(unsigned long data) | |||
299 | ++sta->plink_retries; | 296 | ++sta->plink_retries; |
300 | mod_plink_timer(sta, sta->plink_timeout); | 297 | mod_plink_timer(sta, sta->plink_timeout); |
301 | spin_unlock_bh(&sta->lock); | 298 | spin_unlock_bh(&sta->lock); |
302 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 299 | mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, |
303 | 0, 0); | 300 | 0, 0); |
304 | break; | 301 | break; |
305 | } | 302 | } |
@@ -312,7 +309,7 @@ static void mesh_plink_timer(unsigned long data) | |||
312 | sta->plink_state = PLINK_HOLDING; | 309 | sta->plink_state = PLINK_HOLDING; |
313 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 310 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
314 | spin_unlock_bh(&sta->lock); | 311 | spin_unlock_bh(&sta->lock); |
315 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, | 312 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, |
316 | reason); | 313 | reason); |
317 | break; | 314 | break; |
318 | case PLINK_HOLDING: | 315 | case PLINK_HOLDING: |
@@ -355,10 +352,10 @@ int mesh_plink_open(struct sta_info *sta) | |||
355 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 352 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
356 | spin_unlock_bh(&sta->lock); | 353 | spin_unlock_bh(&sta->lock); |
357 | mpl_dbg("Mesh plink: starting establishment with %s\n", | 354 | mpl_dbg("Mesh plink: starting establishment with %s\n", |
358 | print_mac(mac, sta->addr)); | 355 | print_mac(mac, sta->sta.addr)); |
359 | 356 | ||
360 | return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN, | 357 | return mesh_plink_frame_tx(sdata, PLINK_OPEN, |
361 | sta->addr, llid, 0, 0); | 358 | sta->sta.addr, llid, 0, 0); |
362 | } | 359 | } |
363 | 360 | ||
364 | void mesh_plink_block(struct sta_info *sta) | 361 | void mesh_plink_block(struct sta_info *sta) |
@@ -382,7 +379,7 @@ int mesh_plink_close(struct sta_info *sta) | |||
382 | #endif | 379 | #endif |
383 | 380 | ||
384 | mpl_dbg("Mesh plink: closing link with %s\n", | 381 | mpl_dbg("Mesh plink: closing link with %s\n", |
385 | print_mac(mac, sta->addr)); | 382 | print_mac(mac, sta->sta.addr)); |
386 | spin_lock_bh(&sta->lock); | 383 | spin_lock_bh(&sta->lock); |
387 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); | 384 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); |
388 | reason = sta->reason; | 385 | reason = sta->reason; |
@@ -403,15 +400,14 @@ int mesh_plink_close(struct sta_info *sta) | |||
403 | llid = sta->llid; | 400 | llid = sta->llid; |
404 | plid = sta->plid; | 401 | plid = sta->plid; |
405 | spin_unlock_bh(&sta->lock); | 402 | spin_unlock_bh(&sta->lock); |
406 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, | 403 | mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid, |
407 | plid, reason); | 404 | plid, reason); |
408 | return 0; | 405 | return 0; |
409 | } | 406 | } |
410 | 407 | ||
411 | void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 408 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, |
412 | size_t len, struct ieee80211_rx_status *rx_status) | 409 | size_t len, struct ieee80211_rx_status *rx_status) |
413 | { | 410 | { |
414 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
415 | struct ieee80211_local *local = sdata->local; | 411 | struct ieee80211_local *local = sdata->local; |
416 | struct ieee802_11_elems elems; | 412 | struct ieee802_11_elems elems; |
417 | struct sta_info *sta; | 413 | struct sta_info *sta; |
@@ -425,6 +421,10 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
425 | DECLARE_MAC_BUF(mac); | 421 | DECLARE_MAC_BUF(mac); |
426 | #endif | 422 | #endif |
427 | 423 | ||
424 | /* need action_code, aux */ | ||
425 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | ||
426 | return; | ||
427 | |||
428 | if (is_multicast_ether_addr(mgmt->da)) { | 428 | if (is_multicast_ether_addr(mgmt->da)) { |
429 | mpl_dbg("Mesh plink: ignore frame from multicast address"); | 429 | mpl_dbg("Mesh plink: ignore frame from multicast address"); |
430 | return; | 430 | return; |
@@ -478,7 +478,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
478 | 478 | ||
479 | /* Now we will figure out the appropriate event... */ | 479 | /* Now we will figure out the appropriate event... */ |
480 | event = PLINK_UNDEFINED; | 480 | event = PLINK_UNDEFINED; |
481 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) { | 481 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { |
482 | switch (ftype) { | 482 | switch (ftype) { |
483 | case PLINK_OPEN: | 483 | case PLINK_OPEN: |
484 | event = OPN_RJCT; | 484 | event = OPN_RJCT; |
@@ -577,9 +577,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
577 | sta->llid = llid; | 577 | sta->llid = llid; |
578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
579 | spin_unlock_bh(&sta->lock); | 579 | spin_unlock_bh(&sta->lock); |
580 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 580 | mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, |
581 | 0, 0); | 581 | 0, 0); |
582 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, | 582 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, |
583 | llid, plid, 0); | 583 | llid, plid, 0); |
584 | break; | 584 | break; |
585 | default: | 585 | default: |
@@ -604,7 +604,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
604 | 604 | ||
605 | llid = sta->llid; | 605 | llid = sta->llid; |
606 | spin_unlock_bh(&sta->lock); | 606 | spin_unlock_bh(&sta->lock); |
607 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 607 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
608 | plid, reason); | 608 | plid, reason); |
609 | break; | 609 | break; |
610 | case OPN_ACPT: | 610 | case OPN_ACPT: |
@@ -613,7 +613,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
613 | sta->plid = plid; | 613 | sta->plid = plid; |
614 | llid = sta->llid; | 614 | llid = sta->llid; |
615 | spin_unlock_bh(&sta->lock); | 615 | spin_unlock_bh(&sta->lock); |
616 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 616 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
617 | plid, 0); | 617 | plid, 0); |
618 | break; | 618 | break; |
619 | case CNF_ACPT: | 619 | case CNF_ACPT: |
@@ -646,13 +646,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
646 | 646 | ||
647 | llid = sta->llid; | 647 | llid = sta->llid; |
648 | spin_unlock_bh(&sta->lock); | 648 | spin_unlock_bh(&sta->lock); |
649 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 649 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
650 | plid, reason); | 650 | plid, reason); |
651 | break; | 651 | break; |
652 | case OPN_ACPT: | 652 | case OPN_ACPT: |
653 | llid = sta->llid; | 653 | llid = sta->llid; |
654 | spin_unlock_bh(&sta->lock); | 654 | spin_unlock_bh(&sta->lock); |
655 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 655 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
656 | plid, 0); | 656 | plid, 0); |
657 | break; | 657 | break; |
658 | case CNF_ACPT: | 658 | case CNF_ACPT: |
@@ -661,7 +661,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
661 | mesh_plink_inc_estab_count(sdata); | 661 | mesh_plink_inc_estab_count(sdata); |
662 | spin_unlock_bh(&sta->lock); | 662 | spin_unlock_bh(&sta->lock); |
663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
664 | print_mac(mac, sta->addr)); | 664 | print_mac(mac, sta->sta.addr)); |
665 | break; | 665 | break; |
666 | default: | 666 | default: |
667 | spin_unlock_bh(&sta->lock); | 667 | spin_unlock_bh(&sta->lock); |
@@ -685,7 +685,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
685 | 685 | ||
686 | llid = sta->llid; | 686 | llid = sta->llid; |
687 | spin_unlock_bh(&sta->lock); | 687 | spin_unlock_bh(&sta->lock); |
688 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 688 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
689 | plid, reason); | 689 | plid, reason); |
690 | break; | 690 | break; |
691 | case OPN_ACPT: | 691 | case OPN_ACPT: |
@@ -694,8 +694,8 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
694 | mesh_plink_inc_estab_count(sdata); | 694 | mesh_plink_inc_estab_count(sdata); |
695 | spin_unlock_bh(&sta->lock); | 695 | spin_unlock_bh(&sta->lock); |
696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
697 | print_mac(mac, sta->addr)); | 697 | print_mac(mac, sta->sta.addr)); |
698 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 698 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
699 | plid, 0); | 699 | plid, 0); |
700 | break; | 700 | break; |
701 | default: | 701 | default: |
@@ -714,13 +714,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
714 | llid = sta->llid; | 714 | llid = sta->llid; |
715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
716 | spin_unlock_bh(&sta->lock); | 716 | spin_unlock_bh(&sta->lock); |
717 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 717 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
718 | plid, reason); | 718 | plid, reason); |
719 | break; | 719 | break; |
720 | case OPN_ACPT: | 720 | case OPN_ACPT: |
721 | llid = sta->llid; | 721 | llid = sta->llid; |
722 | spin_unlock_bh(&sta->lock); | 722 | spin_unlock_bh(&sta->lock); |
723 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 723 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
724 | plid, 0); | 724 | plid, 0); |
725 | break; | 725 | break; |
726 | default: | 726 | default: |
@@ -743,8 +743,8 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
743 | llid = sta->llid; | 743 | llid = sta->llid; |
744 | reason = sta->reason; | 744 | reason = sta->reason; |
745 | spin_unlock_bh(&sta->lock); | 745 | spin_unlock_bh(&sta->lock); |
746 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 746 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, |
747 | plid, reason); | 747 | llid, plid, reason); |
748 | break; | 748 | break; |
749 | default: | 749 | default: |
750 | spin_unlock_bh(&sta->lock); | 750 | spin_unlock_bh(&sta->lock); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 902cac1bd246..87665d7bb4f9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -11,11 +11,6 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* TODO: | ||
15 | * order BSS list by RSSI(?) ("quality of AP") | ||
16 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | ||
17 | * SSID) | ||
18 | */ | ||
19 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
20 | #include <linux/if_ether.h> | 15 | #include <linux/if_ether.h> |
21 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
@@ -26,607 +21,184 @@ | |||
26 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
27 | #include <linux/rtnetlink.h> | 22 | #include <linux/rtnetlink.h> |
28 | #include <net/iw_handler.h> | 23 | #include <net/iw_handler.h> |
29 | #include <asm/types.h> | ||
30 | |||
31 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
25 | #include <asm/unaligned.h> | ||
26 | |||
32 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
33 | #include "rate.h" | 28 | #include "rate.h" |
34 | #include "led.h" | 29 | #include "led.h" |
35 | #include "mesh.h" | ||
36 | 30 | ||
31 | #define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 | ||
37 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 32 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
38 | #define IEEE80211_AUTH_MAX_TRIES 3 | 33 | #define IEEE80211_AUTH_MAX_TRIES 3 |
39 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 34 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
40 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 35 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
41 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) | 36 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) |
42 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
43 | #define IEEE80211_PROBE_INTERVAL (60 * HZ) | 37 | #define IEEE80211_PROBE_INTERVAL (60 * HZ) |
44 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) | 38 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) |
45 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) | 39 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) |
46 | #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) | 40 | #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) |
47 | #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) | 41 | #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) |
48 | 42 | ||
49 | #define IEEE80211_PROBE_DELAY (HZ / 33) | ||
50 | #define IEEE80211_CHANNEL_TIME (HZ / 33) | ||
51 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) | ||
52 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | ||
53 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) | 43 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) |
54 | #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) | 44 | #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) |
55 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
56 | 45 | ||
57 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 | 46 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 |
58 | 47 | ||
59 | 48 | ||
60 | #define ERP_INFO_USE_PROTECTION BIT(1) | 49 | /* utils */ |
61 | |||
62 | /* mgmt header + 1 byte action code */ | ||
63 | #define IEEE80211_MIN_ACTION_SIZE (24 + 1) | ||
64 | |||
65 | #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 | ||
66 | #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C | ||
67 | #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 | ||
68 | #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 | ||
69 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 | ||
70 | |||
71 | /* next values represent the buffer size for A-MPDU frame. | ||
72 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */ | ||
73 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | ||
74 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | ||
75 | |||
76 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | ||
77 | u8 *ssid, size_t ssid_len); | ||
78 | static struct ieee80211_sta_bss * | ||
79 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, | ||
80 | u8 *ssid, u8 ssid_len); | ||
81 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
82 | struct ieee80211_sta_bss *bss); | ||
83 | static int ieee80211_sta_find_ibss(struct net_device *dev, | ||
84 | struct ieee80211_if_sta *ifsta); | ||
85 | static int ieee80211_sta_wep_configured(struct net_device *dev); | ||
86 | static int ieee80211_sta_start_scan(struct net_device *dev, | ||
87 | u8 *ssid, size_t ssid_len); | ||
88 | static int ieee80211_sta_config_auth(struct net_device *dev, | ||
89 | struct ieee80211_if_sta *ifsta); | ||
90 | static void sta_rx_agg_session_timer_expired(unsigned long data); | ||
91 | |||
92 | |||
93 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
94 | struct ieee802_11_elems *elems) | ||
95 | { | ||
96 | size_t left = len; | ||
97 | u8 *pos = start; | ||
98 | |||
99 | memset(elems, 0, sizeof(*elems)); | ||
100 | |||
101 | while (left >= 2) { | ||
102 | u8 id, elen; | ||
103 | |||
104 | id = *pos++; | ||
105 | elen = *pos++; | ||
106 | left -= 2; | ||
107 | |||
108 | if (elen > left) | ||
109 | return; | ||
110 | |||
111 | switch (id) { | ||
112 | case WLAN_EID_SSID: | ||
113 | elems->ssid = pos; | ||
114 | elems->ssid_len = elen; | ||
115 | break; | ||
116 | case WLAN_EID_SUPP_RATES: | ||
117 | elems->supp_rates = pos; | ||
118 | elems->supp_rates_len = elen; | ||
119 | break; | ||
120 | case WLAN_EID_FH_PARAMS: | ||
121 | elems->fh_params = pos; | ||
122 | elems->fh_params_len = elen; | ||
123 | break; | ||
124 | case WLAN_EID_DS_PARAMS: | ||
125 | elems->ds_params = pos; | ||
126 | elems->ds_params_len = elen; | ||
127 | break; | ||
128 | case WLAN_EID_CF_PARAMS: | ||
129 | elems->cf_params = pos; | ||
130 | elems->cf_params_len = elen; | ||
131 | break; | ||
132 | case WLAN_EID_TIM: | ||
133 | elems->tim = pos; | ||
134 | elems->tim_len = elen; | ||
135 | break; | ||
136 | case WLAN_EID_IBSS_PARAMS: | ||
137 | elems->ibss_params = pos; | ||
138 | elems->ibss_params_len = elen; | ||
139 | break; | ||
140 | case WLAN_EID_CHALLENGE: | ||
141 | elems->challenge = pos; | ||
142 | elems->challenge_len = elen; | ||
143 | break; | ||
144 | case WLAN_EID_WPA: | ||
145 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
146 | pos[2] == 0xf2) { | ||
147 | /* Microsoft OUI (00:50:F2) */ | ||
148 | if (pos[3] == 1) { | ||
149 | /* OUI Type 1 - WPA IE */ | ||
150 | elems->wpa = pos; | ||
151 | elems->wpa_len = elen; | ||
152 | } else if (elen >= 5 && pos[3] == 2) { | ||
153 | if (pos[4] == 0) { | ||
154 | elems->wmm_info = pos; | ||
155 | elems->wmm_info_len = elen; | ||
156 | } else if (pos[4] == 1) { | ||
157 | elems->wmm_param = pos; | ||
158 | elems->wmm_param_len = elen; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | break; | ||
163 | case WLAN_EID_RSN: | ||
164 | elems->rsn = pos; | ||
165 | elems->rsn_len = elen; | ||
166 | break; | ||
167 | case WLAN_EID_ERP_INFO: | ||
168 | elems->erp_info = pos; | ||
169 | elems->erp_info_len = elen; | ||
170 | break; | ||
171 | case WLAN_EID_EXT_SUPP_RATES: | ||
172 | elems->ext_supp_rates = pos; | ||
173 | elems->ext_supp_rates_len = elen; | ||
174 | break; | ||
175 | case WLAN_EID_HT_CAPABILITY: | ||
176 | elems->ht_cap_elem = pos; | ||
177 | elems->ht_cap_elem_len = elen; | ||
178 | break; | ||
179 | case WLAN_EID_HT_EXTRA_INFO: | ||
180 | elems->ht_info_elem = pos; | ||
181 | elems->ht_info_elem_len = elen; | ||
182 | break; | ||
183 | case WLAN_EID_MESH_ID: | ||
184 | elems->mesh_id = pos; | ||
185 | elems->mesh_id_len = elen; | ||
186 | break; | ||
187 | case WLAN_EID_MESH_CONFIG: | ||
188 | elems->mesh_config = pos; | ||
189 | elems->mesh_config_len = elen; | ||
190 | break; | ||
191 | case WLAN_EID_PEER_LINK: | ||
192 | elems->peer_link = pos; | ||
193 | elems->peer_link_len = elen; | ||
194 | break; | ||
195 | case WLAN_EID_PREQ: | ||
196 | elems->preq = pos; | ||
197 | elems->preq_len = elen; | ||
198 | break; | ||
199 | case WLAN_EID_PREP: | ||
200 | elems->prep = pos; | ||
201 | elems->prep_len = elen; | ||
202 | break; | ||
203 | case WLAN_EID_PERR: | ||
204 | elems->perr = pos; | ||
205 | elems->perr_len = elen; | ||
206 | break; | ||
207 | case WLAN_EID_CHANNEL_SWITCH: | ||
208 | elems->ch_switch_elem = pos; | ||
209 | elems->ch_switch_elem_len = elen; | ||
210 | break; | ||
211 | case WLAN_EID_QUIET: | ||
212 | if (!elems->quiet_elem) { | ||
213 | elems->quiet_elem = pos; | ||
214 | elems->quiet_elem_len = elen; | ||
215 | } | ||
216 | elems->num_of_quiet_elem++; | ||
217 | break; | ||
218 | case WLAN_EID_COUNTRY: | ||
219 | elems->country_elem = pos; | ||
220 | elems->country_elem_len = elen; | ||
221 | break; | ||
222 | case WLAN_EID_PWR_CONSTRAINT: | ||
223 | elems->pwr_constr_elem = pos; | ||
224 | elems->pwr_constr_elem_len = elen; | ||
225 | break; | ||
226 | default: | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | left -= elen; | ||
231 | pos += elen; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | |||
236 | static int ecw2cw(int ecw) | 50 | static int ecw2cw(int ecw) |
237 | { | 51 | { |
238 | return (1 << ecw) - 1; | 52 | return (1 << ecw) - 1; |
239 | } | 53 | } |
240 | 54 | ||
241 | 55 | static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) | |
242 | static void ieee80211_sta_def_wmm_params(struct net_device *dev, | ||
243 | struct ieee80211_sta_bss *bss, | ||
244 | int ibss) | ||
245 | { | ||
246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
247 | struct ieee80211_local *local = sdata->local; | ||
248 | int i, have_higher_than_11mbit = 0; | ||
249 | |||
250 | |||
251 | /* cf. IEEE 802.11 9.2.12 */ | ||
252 | for (i = 0; i < bss->supp_rates_len; i++) | ||
253 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) | ||
254 | have_higher_than_11mbit = 1; | ||
255 | |||
256 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
257 | have_higher_than_11mbit) | ||
258 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
259 | else | ||
260 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
261 | |||
262 | |||
263 | if (local->ops->conf_tx) { | ||
264 | struct ieee80211_tx_queue_params qparam; | ||
265 | |||
266 | memset(&qparam, 0, sizeof(qparam)); | ||
267 | |||
268 | qparam.aifs = 2; | ||
269 | |||
270 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
271 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
272 | qparam.cw_min = 31; | ||
273 | else | ||
274 | qparam.cw_min = 15; | ||
275 | |||
276 | qparam.cw_max = 1023; | ||
277 | qparam.txop = 0; | ||
278 | |||
279 | for (i = 0; i < local_to_hw(local)->queues; i++) | ||
280 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static void ieee80211_sta_wmm_params(struct net_device *dev, | ||
285 | struct ieee80211_if_sta *ifsta, | ||
286 | u8 *wmm_param, size_t wmm_param_len) | ||
287 | { | 56 | { |
288 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 57 | u8 *end, *pos; |
289 | struct ieee80211_tx_queue_params params; | ||
290 | size_t left; | ||
291 | int count; | ||
292 | u8 *pos; | ||
293 | |||
294 | if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED)) | ||
295 | return; | ||
296 | 58 | ||
297 | if (!wmm_param) | 59 | pos = bss->ies; |
298 | return; | 60 | if (pos == NULL) |
299 | 61 | return NULL; | |
300 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) | 62 | end = pos + bss->ies_len; |
301 | return; | ||
302 | count = wmm_param[6] & 0x0f; | ||
303 | if (count == ifsta->wmm_last_param_set) | ||
304 | return; | ||
305 | ifsta->wmm_last_param_set = count; | ||
306 | |||
307 | pos = wmm_param + 8; | ||
308 | left = wmm_param_len - 8; | ||
309 | |||
310 | memset(¶ms, 0, sizeof(params)); | ||
311 | |||
312 | if (!local->ops->conf_tx) | ||
313 | return; | ||
314 | |||
315 | local->wmm_acm = 0; | ||
316 | for (; left >= 4; left -= 4, pos += 4) { | ||
317 | int aci = (pos[0] >> 5) & 0x03; | ||
318 | int acm = (pos[0] >> 4) & 0x01; | ||
319 | int queue; | ||
320 | 63 | ||
321 | switch (aci) { | 64 | while (pos + 1 < end) { |
322 | case 1: | 65 | if (pos + 2 + pos[1] > end) |
323 | queue = 3; | ||
324 | if (acm) | ||
325 | local->wmm_acm |= BIT(0) | BIT(3); | ||
326 | break; | ||
327 | case 2: | ||
328 | queue = 1; | ||
329 | if (acm) | ||
330 | local->wmm_acm |= BIT(4) | BIT(5); | ||
331 | break; | 66 | break; |
332 | case 3: | 67 | if (pos[0] == ie) |
333 | queue = 0; | 68 | return pos; |
334 | if (acm) | 69 | pos += 2 + pos[1]; |
335 | local->wmm_acm |= BIT(6) | BIT(7); | ||
336 | break; | ||
337 | case 0: | ||
338 | default: | ||
339 | queue = 2; | ||
340 | if (acm) | ||
341 | local->wmm_acm |= BIT(1) | BIT(2); | ||
342 | break; | ||
343 | } | ||
344 | |||
345 | params.aifs = pos[0] & 0x0f; | ||
346 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | ||
347 | params.cw_min = ecw2cw(pos[1] & 0x0f); | ||
348 | params.txop = get_unaligned_le16(pos + 2); | ||
349 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
350 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | ||
351 | "cWmin=%d cWmax=%d txop=%d\n", | ||
352 | dev->name, queue, aci, acm, params.aifs, params.cw_min, | ||
353 | params.cw_max, params.txop); | ||
354 | #endif | ||
355 | /* TODO: handle ACM (block TX, fallback to next lowest allowed | ||
356 | * AC for now) */ | ||
357 | if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { | ||
358 | printk(KERN_DEBUG "%s: failed to set TX queue " | ||
359 | "parameters for queue %d\n", dev->name, queue); | ||
360 | } | ||
361 | } | 70 | } |
362 | } | ||
363 | |||
364 | static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | ||
365 | bool use_protection, | ||
366 | bool use_short_preamble) | ||
367 | { | ||
368 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | ||
369 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
370 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
371 | DECLARE_MAC_BUF(mac); | ||
372 | #endif | ||
373 | u32 changed = 0; | ||
374 | 71 | ||
375 | if (use_protection != bss_conf->use_cts_prot) { | 72 | return NULL; |
376 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
377 | if (net_ratelimit()) { | ||
378 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | ||
379 | "%s)\n", | ||
380 | sdata->dev->name, | ||
381 | use_protection ? "enabled" : "disabled", | ||
382 | print_mac(mac, ifsta->bssid)); | ||
383 | } | ||
384 | #endif | ||
385 | bss_conf->use_cts_prot = use_protection; | ||
386 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
387 | } | ||
388 | |||
389 | if (use_short_preamble != bss_conf->use_short_preamble) { | ||
390 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
391 | if (net_ratelimit()) { | ||
392 | printk(KERN_DEBUG "%s: switched to %s barker preamble" | ||
393 | " (BSSID=%s)\n", | ||
394 | sdata->dev->name, | ||
395 | use_short_preamble ? "short" : "long", | ||
396 | print_mac(mac, ifsta->bssid)); | ||
397 | } | ||
398 | #endif | ||
399 | bss_conf->use_short_preamble = use_short_preamble; | ||
400 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
401 | } | ||
402 | |||
403 | return changed; | ||
404 | } | ||
405 | |||
406 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | ||
407 | u8 erp_value) | ||
408 | { | ||
409 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | ||
410 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; | ||
411 | |||
412 | return ieee80211_handle_protect_preamb(sdata, | ||
413 | use_protection, use_short_preamble); | ||
414 | } | 73 | } |
415 | 74 | ||
416 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 75 | static int ieee80211_compatible_rates(struct ieee80211_bss *bss, |
417 | struct ieee80211_sta_bss *bss) | 76 | struct ieee80211_supported_band *sband, |
77 | u64 *rates) | ||
418 | { | 78 | { |
419 | u32 changed = 0; | 79 | int i, j, count; |
80 | *rates = 0; | ||
81 | count = 0; | ||
82 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
83 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | ||
420 | 84 | ||
421 | if (bss->has_erp_value) | 85 | for (j = 0; j < sband->n_bitrates; j++) |
422 | changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); | 86 | if (sband->bitrates[j].bitrate == rate) { |
423 | else { | 87 | *rates |= BIT(j); |
424 | u16 capab = bss->capability; | 88 | count++; |
425 | changed |= ieee80211_handle_protect_preamb(sdata, false, | 89 | break; |
426 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); | 90 | } |
427 | } | 91 | } |
428 | 92 | ||
429 | return changed; | 93 | return count; |
430 | } | ||
431 | |||
432 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
433 | struct ieee80211_ht_info *ht_info) | ||
434 | { | ||
435 | |||
436 | if (ht_info == NULL) | ||
437 | return -EINVAL; | ||
438 | |||
439 | memset(ht_info, 0, sizeof(*ht_info)); | ||
440 | |||
441 | if (ht_cap_ie) { | ||
442 | u8 ampdu_info = ht_cap_ie->ampdu_params_info; | ||
443 | |||
444 | ht_info->ht_supported = 1; | ||
445 | ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); | ||
446 | ht_info->ampdu_factor = | ||
447 | ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; | ||
448 | ht_info->ampdu_density = | ||
449 | (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; | ||
450 | memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); | ||
451 | } else | ||
452 | ht_info->ht_supported = 0; | ||
453 | |||
454 | return 0; | ||
455 | } | 94 | } |
456 | 95 | ||
457 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | 96 | /* also used by mesh code */ |
458 | struct ieee80211_ht_addt_info *ht_add_info_ie, | 97 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
459 | struct ieee80211_ht_bss_info *bss_info) | 98 | struct ieee802_11_elems *elems, |
99 | enum ieee80211_band band) | ||
460 | { | 100 | { |
461 | if (bss_info == NULL) | 101 | struct ieee80211_supported_band *sband; |
462 | return -EINVAL; | 102 | struct ieee80211_rate *bitrates; |
463 | 103 | size_t num_rates; | |
464 | memset(bss_info, 0, sizeof(*bss_info)); | 104 | u64 supp_rates; |
465 | 105 | int i, j; | |
466 | if (ht_add_info_ie) { | 106 | sband = local->hw.wiphy->bands[band]; |
467 | u16 op_mode; | ||
468 | op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); | ||
469 | 107 | ||
470 | bss_info->primary_channel = ht_add_info_ie->control_chan; | 108 | if (!sband) { |
471 | bss_info->bss_cap = ht_add_info_ie->ht_param; | 109 | WARN_ON(1); |
472 | bss_info->bss_op_mode = (u8)(op_mode & 0xff); | 110 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
473 | } | 111 | } |
474 | 112 | ||
475 | return 0; | 113 | bitrates = sband->bitrates; |
114 | num_rates = sband->n_bitrates; | ||
115 | supp_rates = 0; | ||
116 | for (i = 0; i < elems->supp_rates_len + | ||
117 | elems->ext_supp_rates_len; i++) { | ||
118 | u8 rate = 0; | ||
119 | int own_rate; | ||
120 | if (i < elems->supp_rates_len) | ||
121 | rate = elems->supp_rates[i]; | ||
122 | else if (elems->ext_supp_rates) | ||
123 | rate = elems->ext_supp_rates | ||
124 | [i - elems->supp_rates_len]; | ||
125 | own_rate = 5 * (rate & 0x7f); | ||
126 | for (j = 0; j < num_rates; j++) | ||
127 | if (bitrates[j].bitrate == own_rate) | ||
128 | supp_rates |= BIT(j); | ||
129 | } | ||
130 | return supp_rates; | ||
476 | } | 131 | } |
477 | 132 | ||
478 | static void ieee80211_sta_send_associnfo(struct net_device *dev, | 133 | /* frame sending functions */ |
479 | struct ieee80211_if_sta *ifsta) | 134 | |
135 | /* also used by scanning code */ | ||
136 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | ||
137 | u8 *ssid, size_t ssid_len) | ||
480 | { | 138 | { |
481 | char *buf; | 139 | struct ieee80211_local *local = sdata->local; |
482 | size_t len; | 140 | struct ieee80211_supported_band *sband; |
141 | struct sk_buff *skb; | ||
142 | struct ieee80211_mgmt *mgmt; | ||
143 | u8 *pos, *supp_rates, *esupp_rates = NULL; | ||
483 | int i; | 144 | int i; |
484 | union iwreq_data wrqu; | ||
485 | |||
486 | if (!ifsta->assocreq_ies && !ifsta->assocresp_ies) | ||
487 | return; | ||
488 | 145 | ||
489 | buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + | 146 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); |
490 | ifsta->assocresp_ies_len), GFP_KERNEL); | 147 | if (!skb) { |
491 | if (!buf) | 148 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
149 | "request\n", sdata->dev->name); | ||
492 | return; | 150 | return; |
493 | |||
494 | len = sprintf(buf, "ASSOCINFO("); | ||
495 | if (ifsta->assocreq_ies) { | ||
496 | len += sprintf(buf + len, "ReqIEs="); | ||
497 | for (i = 0; i < ifsta->assocreq_ies_len; i++) { | ||
498 | len += sprintf(buf + len, "%02x", | ||
499 | ifsta->assocreq_ies[i]); | ||
500 | } | ||
501 | } | 151 | } |
502 | if (ifsta->assocresp_ies) { | 152 | skb_reserve(skb, local->hw.extra_tx_headroom); |
503 | if (ifsta->assocreq_ies) | ||
504 | len += sprintf(buf + len, " "); | ||
505 | len += sprintf(buf + len, "RespIEs="); | ||
506 | for (i = 0; i < ifsta->assocresp_ies_len; i++) { | ||
507 | len += sprintf(buf + len, "%02x", | ||
508 | ifsta->assocresp_ies[i]); | ||
509 | } | ||
510 | } | ||
511 | len += sprintf(buf + len, ")"); | ||
512 | 153 | ||
513 | if (len > IW_CUSTOM_MAX) { | 154 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
514 | len = sprintf(buf, "ASSOCRESPIE="); | 155 | memset(mgmt, 0, 24); |
515 | for (i = 0; i < ifsta->assocresp_ies_len; i++) { | 156 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
516 | len += sprintf(buf + len, "%02x", | 157 | IEEE80211_STYPE_PROBE_REQ); |
517 | ifsta->assocresp_ies[i]); | 158 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
518 | } | 159 | if (dst) { |
160 | memcpy(mgmt->da, dst, ETH_ALEN); | ||
161 | memcpy(mgmt->bssid, dst, ETH_ALEN); | ||
162 | } else { | ||
163 | memset(mgmt->da, 0xff, ETH_ALEN); | ||
164 | memset(mgmt->bssid, 0xff, ETH_ALEN); | ||
519 | } | 165 | } |
166 | pos = skb_put(skb, 2 + ssid_len); | ||
167 | *pos++ = WLAN_EID_SSID; | ||
168 | *pos++ = ssid_len; | ||
169 | memcpy(pos, ssid, ssid_len); | ||
520 | 170 | ||
521 | memset(&wrqu, 0, sizeof(wrqu)); | 171 | supp_rates = skb_put(skb, 2); |
522 | wrqu.data.length = len; | 172 | supp_rates[0] = WLAN_EID_SUPP_RATES; |
523 | wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); | 173 | supp_rates[1] = 0; |
524 | 174 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | |
525 | kfree(buf); | ||
526 | } | ||
527 | |||
528 | |||
529 | static void ieee80211_set_associated(struct net_device *dev, | ||
530 | struct ieee80211_if_sta *ifsta, | ||
531 | bool assoc) | ||
532 | { | ||
533 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
534 | struct ieee80211_local *local = sdata->local; | ||
535 | struct ieee80211_conf *conf = &local_to_hw(local)->conf; | ||
536 | union iwreq_data wrqu; | ||
537 | u32 changed = BSS_CHANGED_ASSOC; | ||
538 | |||
539 | if (assoc) { | ||
540 | struct ieee80211_sta_bss *bss; | ||
541 | |||
542 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; | ||
543 | |||
544 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
545 | return; | ||
546 | |||
547 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | ||
548 | conf->channel->center_freq, | ||
549 | ifsta->ssid, ifsta->ssid_len); | ||
550 | if (bss) { | ||
551 | /* set timing information */ | ||
552 | sdata->bss_conf.beacon_int = bss->beacon_int; | ||
553 | sdata->bss_conf.timestamp = bss->timestamp; | ||
554 | sdata->bss_conf.dtim_period = bss->dtim_period; | ||
555 | |||
556 | changed |= ieee80211_handle_bss_capability(sdata, bss); | ||
557 | |||
558 | ieee80211_rx_bss_put(local, bss); | ||
559 | } | ||
560 | 175 | ||
561 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 176 | for (i = 0; i < sband->n_bitrates; i++) { |
562 | changed |= BSS_CHANGED_HT; | 177 | struct ieee80211_rate *rate = &sband->bitrates[i]; |
563 | sdata->bss_conf.assoc_ht = 1; | 178 | if (esupp_rates) { |
564 | sdata->bss_conf.ht_conf = &conf->ht_conf; | 179 | pos = skb_put(skb, 1); |
565 | sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; | 180 | esupp_rates[1]++; |
181 | } else if (supp_rates[1] == 8) { | ||
182 | esupp_rates = skb_put(skb, 3); | ||
183 | esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; | ||
184 | esupp_rates[1] = 1; | ||
185 | pos = &esupp_rates[2]; | ||
186 | } else { | ||
187 | pos = skb_put(skb, 1); | ||
188 | supp_rates[1]++; | ||
566 | } | 189 | } |
567 | 190 | *pos = rate->bitrate / 5; | |
568 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; | ||
569 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); | ||
570 | memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); | ||
571 | ieee80211_sta_send_associnfo(dev, ifsta); | ||
572 | } else { | ||
573 | netif_carrier_off(dev); | ||
574 | ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); | ||
575 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | ||
576 | changed |= ieee80211_reset_erp_info(dev); | ||
577 | |||
578 | sdata->bss_conf.assoc_ht = 0; | ||
579 | sdata->bss_conf.ht_conf = NULL; | ||
580 | sdata->bss_conf.ht_bss_conf = NULL; | ||
581 | |||
582 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | ||
583 | } | 191 | } |
584 | ifsta->last_probe = jiffies; | ||
585 | ieee80211_led_assoc(local, assoc); | ||
586 | 192 | ||
587 | sdata->bss_conf.assoc = assoc; | 193 | ieee80211_tx_skb(sdata, skb, 0); |
588 | ieee80211_bss_info_change_notify(sdata, changed); | ||
589 | |||
590 | if (assoc) | ||
591 | netif_carrier_on(dev); | ||
592 | |||
593 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
594 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | ||
595 | } | 194 | } |
596 | 195 | ||
597 | static void ieee80211_set_disassoc(struct net_device *dev, | 196 | static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
598 | struct ieee80211_if_sta *ifsta, int deauth) | ||
599 | { | ||
600 | if (deauth) | ||
601 | ifsta->auth_tries = 0; | ||
602 | ifsta->assoc_tries = 0; | ||
603 | ieee80211_set_associated(dev, ifsta, 0); | ||
604 | } | ||
605 | |||
606 | void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | ||
607 | int encrypt) | ||
608 | { | ||
609 | struct ieee80211_sub_if_data *sdata; | ||
610 | |||
611 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
612 | skb->dev = sdata->local->mdev; | ||
613 | skb_set_mac_header(skb, 0); | ||
614 | skb_set_network_header(skb, 0); | ||
615 | skb_set_transport_header(skb, 0); | ||
616 | |||
617 | skb->iif = sdata->dev->ifindex; | ||
618 | skb->do_not_encrypt = !encrypt; | ||
619 | |||
620 | dev_queue_xmit(skb); | ||
621 | } | ||
622 | |||
623 | |||
624 | static void ieee80211_send_auth(struct net_device *dev, | ||
625 | struct ieee80211_if_sta *ifsta, | 197 | struct ieee80211_if_sta *ifsta, |
626 | int transaction, u8 *extra, size_t extra_len, | 198 | int transaction, u8 *extra, size_t extra_len, |
627 | int encrypt) | 199 | int encrypt) |
628 | { | 200 | { |
629 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 201 | struct ieee80211_local *local = sdata->local; |
630 | struct sk_buff *skb; | 202 | struct sk_buff *skb; |
631 | struct ieee80211_mgmt *mgmt; | 203 | struct ieee80211_mgmt *mgmt; |
632 | 204 | ||
@@ -634,19 +206,19 @@ static void ieee80211_send_auth(struct net_device *dev, | |||
634 | sizeof(*mgmt) + 6 + extra_len); | 206 | sizeof(*mgmt) + 6 + extra_len); |
635 | if (!skb) { | 207 | if (!skb) { |
636 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | 208 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " |
637 | "frame\n", dev->name); | 209 | "frame\n", sdata->dev->name); |
638 | return; | 210 | return; |
639 | } | 211 | } |
640 | skb_reserve(skb, local->hw.extra_tx_headroom); | 212 | skb_reserve(skb, local->hw.extra_tx_headroom); |
641 | 213 | ||
642 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); | 214 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); |
643 | memset(mgmt, 0, 24 + 6); | 215 | memset(mgmt, 0, 24 + 6); |
644 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 216 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
645 | IEEE80211_STYPE_AUTH); | 217 | IEEE80211_STYPE_AUTH); |
646 | if (encrypt) | 218 | if (encrypt) |
647 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 219 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
648 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 220 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); |
649 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 221 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
650 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 222 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
651 | mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); | 223 | mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); |
652 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); | 224 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); |
@@ -655,64 +227,19 @@ static void ieee80211_send_auth(struct net_device *dev, | |||
655 | if (extra) | 227 | if (extra) |
656 | memcpy(skb_put(skb, extra_len), extra, extra_len); | 228 | memcpy(skb_put(skb, extra_len), extra, extra_len); |
657 | 229 | ||
658 | ieee80211_sta_tx(dev, skb, encrypt); | 230 | ieee80211_tx_skb(sdata, skb, encrypt); |
659 | } | ||
660 | |||
661 | |||
662 | static void ieee80211_authenticate(struct net_device *dev, | ||
663 | struct ieee80211_if_sta *ifsta) | ||
664 | { | ||
665 | DECLARE_MAC_BUF(mac); | ||
666 | |||
667 | ifsta->auth_tries++; | ||
668 | if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | ||
669 | printk(KERN_DEBUG "%s: authentication with AP %s" | ||
670 | " timed out\n", | ||
671 | dev->name, print_mac(mac, ifsta->bssid)); | ||
672 | ifsta->state = IEEE80211_DISABLED; | ||
673 | return; | ||
674 | } | ||
675 | |||
676 | ifsta->state = IEEE80211_AUTHENTICATE; | ||
677 | printk(KERN_DEBUG "%s: authenticate with AP %s\n", | ||
678 | dev->name, print_mac(mac, ifsta->bssid)); | ||
679 | |||
680 | ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); | ||
681 | |||
682 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | ||
683 | } | ||
684 | |||
685 | static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, | ||
686 | struct ieee80211_supported_band *sband, | ||
687 | u64 *rates) | ||
688 | { | ||
689 | int i, j, count; | ||
690 | *rates = 0; | ||
691 | count = 0; | ||
692 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
693 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | ||
694 | |||
695 | for (j = 0; j < sband->n_bitrates; j++) | ||
696 | if (sband->bitrates[j].bitrate == rate) { | ||
697 | *rates |= BIT(j); | ||
698 | count++; | ||
699 | break; | ||
700 | } | ||
701 | } | ||
702 | |||
703 | return count; | ||
704 | } | 231 | } |
705 | 232 | ||
706 | static void ieee80211_send_assoc(struct net_device *dev, | 233 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, |
707 | struct ieee80211_if_sta *ifsta) | 234 | struct ieee80211_if_sta *ifsta) |
708 | { | 235 | { |
709 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 236 | struct ieee80211_local *local = sdata->local; |
710 | struct sk_buff *skb; | 237 | struct sk_buff *skb; |
711 | struct ieee80211_mgmt *mgmt; | 238 | struct ieee80211_mgmt *mgmt; |
712 | u8 *pos, *ies; | 239 | u8 *pos, *ies, *ht_add_ie; |
713 | int i, len, count, rates_len, supp_rates_len; | 240 | int i, len, count, rates_len, supp_rates_len; |
714 | u16 capab; | 241 | u16 capab; |
715 | struct ieee80211_sta_bss *bss; | 242 | struct ieee80211_bss *bss; |
716 | int wmm = 0; | 243 | int wmm = 0; |
717 | struct ieee80211_supported_band *sband; | 244 | struct ieee80211_supported_band *sband; |
718 | u64 rates = 0; | 245 | u64 rates = 0; |
@@ -722,7 +249,7 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
722 | ifsta->ssid_len); | 249 | ifsta->ssid_len); |
723 | if (!skb) { | 250 | if (!skb) { |
724 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | 251 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " |
725 | "frame\n", dev->name); | 252 | "frame\n", sdata->dev->name); |
726 | return; | 253 | return; |
727 | } | 254 | } |
728 | skb_reserve(skb, local->hw.extra_tx_headroom); | 255 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -738,13 +265,13 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
738 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | 265 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; |
739 | } | 266 | } |
740 | 267 | ||
741 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 268 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
742 | local->hw.conf.channel->center_freq, | 269 | local->hw.conf.channel->center_freq, |
743 | ifsta->ssid, ifsta->ssid_len); | 270 | ifsta->ssid, ifsta->ssid_len); |
744 | if (bss) { | 271 | if (bss) { |
745 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 272 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
746 | capab |= WLAN_CAPABILITY_PRIVACY; | 273 | capab |= WLAN_CAPABILITY_PRIVACY; |
747 | if (bss->wmm_ie) | 274 | if (bss->wmm_used) |
748 | wmm = 1; | 275 | wmm = 1; |
749 | 276 | ||
750 | /* get all rates supported by the device and the AP as | 277 | /* get all rates supported by the device and the AP as |
@@ -766,13 +293,13 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
766 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 293 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
767 | memset(mgmt, 0, 24); | 294 | memset(mgmt, 0, 24); |
768 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 295 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); |
769 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 296 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
770 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 297 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
771 | 298 | ||
772 | if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { | 299 | if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { |
773 | skb_put(skb, 10); | 300 | skb_put(skb, 10); |
774 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 301 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
775 | IEEE80211_STYPE_REASSOC_REQ); | 302 | IEEE80211_STYPE_REASSOC_REQ); |
776 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | 303 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); |
777 | mgmt->u.reassoc_req.listen_interval = | 304 | mgmt->u.reassoc_req.listen_interval = |
778 | cpu_to_le16(local->hw.conf.listen_interval); | 305 | cpu_to_le16(local->hw.conf.listen_interval); |
@@ -780,8 +307,8 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
780 | ETH_ALEN); | 307 | ETH_ALEN); |
781 | } else { | 308 | } else { |
782 | skb_put(skb, 4); | 309 | skb_put(skb, 4); |
783 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 310 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
784 | IEEE80211_STYPE_ASSOC_REQ); | 311 | IEEE80211_STYPE_ASSOC_REQ); |
785 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | 312 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); |
786 | mgmt->u.reassoc_req.listen_interval = | 313 | mgmt->u.reassoc_req.listen_interval = |
787 | cpu_to_le16(local->hw.conf.listen_interval); | 314 | cpu_to_le16(local->hw.conf.listen_interval); |
@@ -866,9 +393,10 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
866 | 393 | ||
867 | /* wmm support is a must to HT */ | 394 | /* wmm support is a must to HT */ |
868 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && | 395 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && |
869 | sband->ht_info.ht_supported && bss->ht_add_ie) { | 396 | sband->ht_info.ht_supported && |
397 | (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { | ||
870 | struct ieee80211_ht_addt_info *ht_add_info = | 398 | struct ieee80211_ht_addt_info *ht_add_info = |
871 | (struct ieee80211_ht_addt_info *)bss->ht_add_ie; | 399 | (struct ieee80211_ht_addt_info *)ht_add_ie; |
872 | u16 cap = sband->ht_info.cap; | 400 | u16 cap = sband->ht_info.cap; |
873 | __le16 tmp; | 401 | __le16 tmp; |
874 | u32 flags = local->hw.conf.channel->flags; | 402 | u32 flags = local->hw.conf.channel->flags; |
@@ -907,21 +435,22 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
907 | if (ifsta->assocreq_ies) | 435 | if (ifsta->assocreq_ies) |
908 | memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); | 436 | memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); |
909 | 437 | ||
910 | ieee80211_sta_tx(dev, skb, 0); | 438 | ieee80211_tx_skb(sdata, skb, 0); |
911 | } | 439 | } |
912 | 440 | ||
913 | 441 | ||
914 | static void ieee80211_send_deauth(struct net_device *dev, | 442 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
915 | struct ieee80211_if_sta *ifsta, u16 reason) | 443 | u16 stype, u16 reason) |
916 | { | 444 | { |
917 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 445 | struct ieee80211_local *local = sdata->local; |
446 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
918 | struct sk_buff *skb; | 447 | struct sk_buff *skb; |
919 | struct ieee80211_mgmt *mgmt; | 448 | struct ieee80211_mgmt *mgmt; |
920 | 449 | ||
921 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 450 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); |
922 | if (!skb) { | 451 | if (!skb) { |
923 | printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " | 452 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
924 | "frame\n", dev->name); | 453 | "deauth/disassoc frame\n", sdata->dev->name); |
925 | return; | 454 | return; |
926 | } | 455 | } |
927 | skb_reserve(skb, local->hw.extra_tx_headroom); | 456 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -929,940 +458,594 @@ static void ieee80211_send_deauth(struct net_device *dev, | |||
929 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 458 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
930 | memset(mgmt, 0, 24); | 459 | memset(mgmt, 0, 24); |
931 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 460 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); |
932 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 461 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
933 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 462 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
934 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 463 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); |
935 | IEEE80211_STYPE_DEAUTH); | ||
936 | skb_put(skb, 2); | 464 | skb_put(skb, 2); |
465 | /* u.deauth.reason_code == u.disassoc.reason_code */ | ||
937 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | 466 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); |
938 | 467 | ||
939 | ieee80211_sta_tx(dev, skb, 0); | 468 | ieee80211_tx_skb(sdata, skb, 0); |
940 | } | 469 | } |
941 | 470 | ||
942 | 471 | /* MLME */ | |
943 | static void ieee80211_send_disassoc(struct net_device *dev, | 472 | static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
944 | struct ieee80211_if_sta *ifsta, u16 reason) | 473 | struct ieee80211_bss *bss) |
945 | { | 474 | { |
946 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 475 | struct ieee80211_local *local = sdata->local; |
947 | struct sk_buff *skb; | 476 | int i, have_higher_than_11mbit = 0; |
948 | struct ieee80211_mgmt *mgmt; | ||
949 | 477 | ||
950 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 478 | /* cf. IEEE 802.11 9.2.12 */ |
951 | if (!skb) { | 479 | for (i = 0; i < bss->supp_rates_len; i++) |
952 | printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " | 480 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) |
953 | "frame\n", dev->name); | 481 | have_higher_than_11mbit = 1; |
954 | return; | ||
955 | } | ||
956 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
957 | 482 | ||
958 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 483 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
959 | memset(mgmt, 0, 24); | 484 | have_higher_than_11mbit) |
960 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 485 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
961 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 486 | else |
962 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 487 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
963 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
964 | IEEE80211_STYPE_DISASSOC); | ||
965 | skb_put(skb, 2); | ||
966 | mgmt->u.disassoc.reason_code = cpu_to_le16(reason); | ||
967 | 488 | ||
968 | ieee80211_sta_tx(dev, skb, 0); | 489 | ieee80211_set_wmm_default(sdata); |
969 | } | 490 | } |
970 | 491 | ||
971 | 492 | static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |
972 | static int ieee80211_privacy_mismatch(struct net_device *dev, | 493 | struct ieee80211_if_sta *ifsta, |
973 | struct ieee80211_if_sta *ifsta) | 494 | u8 *wmm_param, size_t wmm_param_len) |
974 | { | 495 | { |
975 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 496 | struct ieee80211_tx_queue_params params; |
976 | struct ieee80211_sta_bss *bss; | 497 | size_t left; |
977 | int bss_privacy; | 498 | int count; |
978 | int wep_privacy; | 499 | u8 *pos; |
979 | int privacy_invoked; | ||
980 | 500 | ||
981 | if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) | 501 | if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED)) |
982 | return 0; | 502 | return; |
983 | 503 | ||
984 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 504 | if (!wmm_param) |
985 | local->hw.conf.channel->center_freq, | 505 | return; |
986 | ifsta->ssid, ifsta->ssid_len); | ||
987 | if (!bss) | ||
988 | return 0; | ||
989 | 506 | ||
990 | bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); | 507 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) |
991 | wep_privacy = !!ieee80211_sta_wep_configured(dev); | 508 | return; |
992 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | 509 | count = wmm_param[6] & 0x0f; |
510 | if (count == ifsta->wmm_last_param_set) | ||
511 | return; | ||
512 | ifsta->wmm_last_param_set = count; | ||
993 | 513 | ||
994 | ieee80211_rx_bss_put(local, bss); | 514 | pos = wmm_param + 8; |
515 | left = wmm_param_len - 8; | ||
995 | 516 | ||
996 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) | 517 | memset(¶ms, 0, sizeof(params)); |
997 | return 0; | ||
998 | 518 | ||
999 | return 1; | 519 | if (!local->ops->conf_tx) |
1000 | } | 520 | return; |
1001 | 521 | ||
522 | local->wmm_acm = 0; | ||
523 | for (; left >= 4; left -= 4, pos += 4) { | ||
524 | int aci = (pos[0] >> 5) & 0x03; | ||
525 | int acm = (pos[0] >> 4) & 0x01; | ||
526 | int queue; | ||
1002 | 527 | ||
1003 | static void ieee80211_associate(struct net_device *dev, | 528 | switch (aci) { |
1004 | struct ieee80211_if_sta *ifsta) | 529 | case 1: |
530 | queue = 3; | ||
531 | if (acm) | ||
532 | local->wmm_acm |= BIT(0) | BIT(3); | ||
533 | break; | ||
534 | case 2: | ||
535 | queue = 1; | ||
536 | if (acm) | ||
537 | local->wmm_acm |= BIT(4) | BIT(5); | ||
538 | break; | ||
539 | case 3: | ||
540 | queue = 0; | ||
541 | if (acm) | ||
542 | local->wmm_acm |= BIT(6) | BIT(7); | ||
543 | break; | ||
544 | case 0: | ||
545 | default: | ||
546 | queue = 2; | ||
547 | if (acm) | ||
548 | local->wmm_acm |= BIT(1) | BIT(2); | ||
549 | break; | ||
550 | } | ||
551 | |||
552 | params.aifs = pos[0] & 0x0f; | ||
553 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | ||
554 | params.cw_min = ecw2cw(pos[1] & 0x0f); | ||
555 | params.txop = get_unaligned_le16(pos + 2); | ||
556 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
557 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | ||
558 | "cWmin=%d cWmax=%d txop=%d\n", | ||
559 | local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, | ||
560 | params.cw_max, params.txop); | ||
561 | #endif | ||
562 | /* TODO: handle ACM (block TX, fallback to next lowest allowed | ||
563 | * AC for now) */ | ||
564 | if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { | ||
565 | printk(KERN_DEBUG "%s: failed to set TX queue " | ||
566 | "parameters for queue %d\n", local->mdev->name, queue); | ||
567 | } | ||
568 | } | ||
569 | } | ||
570 | |||
571 | static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | ||
572 | bool use_protection, | ||
573 | bool use_short_preamble) | ||
1005 | { | 574 | { |
575 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | ||
576 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
577 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1006 | DECLARE_MAC_BUF(mac); | 578 | DECLARE_MAC_BUF(mac); |
579 | #endif | ||
580 | u32 changed = 0; | ||
1007 | 581 | ||
1008 | ifsta->assoc_tries++; | 582 | if (use_protection != bss_conf->use_cts_prot) { |
1009 | if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { | 583 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1010 | printk(KERN_DEBUG "%s: association with AP %s" | 584 | if (net_ratelimit()) { |
1011 | " timed out\n", | 585 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" |
1012 | dev->name, print_mac(mac, ifsta->bssid)); | 586 | "%s)\n", |
1013 | ifsta->state = IEEE80211_DISABLED; | 587 | sdata->dev->name, |
1014 | return; | 588 | use_protection ? "enabled" : "disabled", |
589 | print_mac(mac, ifsta->bssid)); | ||
590 | } | ||
591 | #endif | ||
592 | bss_conf->use_cts_prot = use_protection; | ||
593 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
1015 | } | 594 | } |
1016 | 595 | ||
1017 | ifsta->state = IEEE80211_ASSOCIATE; | 596 | if (use_short_preamble != bss_conf->use_short_preamble) { |
1018 | printk(KERN_DEBUG "%s: associate with AP %s\n", | 597 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1019 | dev->name, print_mac(mac, ifsta->bssid)); | 598 | if (net_ratelimit()) { |
1020 | if (ieee80211_privacy_mismatch(dev, ifsta)) { | 599 | printk(KERN_DEBUG "%s: switched to %s barker preamble" |
1021 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " | 600 | " (BSSID=%s)\n", |
1022 | "mixed-cell disabled - abort association\n", dev->name); | 601 | sdata->dev->name, |
1023 | ifsta->state = IEEE80211_DISABLED; | 602 | use_short_preamble ? "short" : "long", |
1024 | return; | 603 | print_mac(mac, ifsta->bssid)); |
604 | } | ||
605 | #endif | ||
606 | bss_conf->use_short_preamble = use_short_preamble; | ||
607 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
1025 | } | 608 | } |
1026 | 609 | ||
1027 | ieee80211_send_assoc(dev, ifsta); | 610 | return changed; |
1028 | |||
1029 | mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); | ||
1030 | } | 611 | } |
1031 | 612 | ||
1032 | 613 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | |
1033 | static void ieee80211_associated(struct net_device *dev, | 614 | u8 erp_value) |
1034 | struct ieee80211_if_sta *ifsta) | ||
1035 | { | 615 | { |
1036 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 616 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; |
1037 | struct sta_info *sta; | 617 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; |
1038 | int disassoc; | ||
1039 | DECLARE_MAC_BUF(mac); | ||
1040 | |||
1041 | /* TODO: start monitoring current AP signal quality and number of | ||
1042 | * missed beacons. Scan other channels every now and then and search | ||
1043 | * for better APs. */ | ||
1044 | /* TODO: remove expired BSSes */ | ||
1045 | 618 | ||
1046 | ifsta->state = IEEE80211_ASSOCIATED; | 619 | return ieee80211_handle_protect_preamb(sdata, |
620 | use_protection, use_short_preamble); | ||
621 | } | ||
1047 | 622 | ||
1048 | rcu_read_lock(); | 623 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
624 | struct ieee80211_bss *bss) | ||
625 | { | ||
626 | u32 changed = 0; | ||
1049 | 627 | ||
1050 | sta = sta_info_get(local, ifsta->bssid); | 628 | if (bss->has_erp_value) |
1051 | if (!sta) { | 629 | changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); |
1052 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", | 630 | else { |
1053 | dev->name, print_mac(mac, ifsta->bssid)); | 631 | u16 capab = bss->capability; |
1054 | disassoc = 1; | 632 | changed |= ieee80211_handle_protect_preamb(sdata, false, |
1055 | } else { | 633 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); |
1056 | disassoc = 0; | ||
1057 | if (time_after(jiffies, | ||
1058 | sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { | ||
1059 | if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) { | ||
1060 | printk(KERN_DEBUG "%s: No ProbeResp from " | ||
1061 | "current AP %s - assume out of " | ||
1062 | "range\n", | ||
1063 | dev->name, print_mac(mac, ifsta->bssid)); | ||
1064 | disassoc = 1; | ||
1065 | sta_info_unlink(&sta); | ||
1066 | } else | ||
1067 | ieee80211_send_probe_req(dev, ifsta->bssid, | ||
1068 | local->scan_ssid, | ||
1069 | local->scan_ssid_len); | ||
1070 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | ||
1071 | } else { | ||
1072 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | ||
1073 | if (time_after(jiffies, ifsta->last_probe + | ||
1074 | IEEE80211_PROBE_INTERVAL)) { | ||
1075 | ifsta->last_probe = jiffies; | ||
1076 | ieee80211_send_probe_req(dev, ifsta->bssid, | ||
1077 | ifsta->ssid, | ||
1078 | ifsta->ssid_len); | ||
1079 | } | ||
1080 | } | ||
1081 | } | 634 | } |
1082 | 635 | ||
1083 | rcu_read_unlock(); | 636 | return changed; |
1084 | |||
1085 | if (disassoc && sta) | ||
1086 | sta_info_destroy(sta); | ||
1087 | |||
1088 | if (disassoc) { | ||
1089 | ifsta->state = IEEE80211_DISABLED; | ||
1090 | ieee80211_set_associated(dev, ifsta, 0); | ||
1091 | } else { | ||
1092 | mod_timer(&ifsta->timer, jiffies + | ||
1093 | IEEE80211_MONITORING_INTERVAL); | ||
1094 | } | ||
1095 | } | 637 | } |
1096 | 638 | ||
639 | static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, | ||
640 | struct ieee80211_if_sta *ifsta) | ||
641 | { | ||
642 | union iwreq_data wrqu; | ||
643 | memset(&wrqu, 0, sizeof(wrqu)); | ||
644 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) | ||
645 | memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); | ||
646 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
647 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | ||
648 | } | ||
1097 | 649 | ||
1098 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | 650 | static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, |
1099 | u8 *ssid, size_t ssid_len) | 651 | struct ieee80211_if_sta *ifsta) |
1100 | { | 652 | { |
1101 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 653 | char *buf; |
1102 | struct ieee80211_supported_band *sband; | 654 | size_t len; |
1103 | struct sk_buff *skb; | ||
1104 | struct ieee80211_mgmt *mgmt; | ||
1105 | u8 *pos, *supp_rates, *esupp_rates = NULL; | ||
1106 | int i; | 655 | int i; |
656 | union iwreq_data wrqu; | ||
1107 | 657 | ||
1108 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); | 658 | if (!ifsta->assocreq_ies && !ifsta->assocresp_ies) |
1109 | if (!skb) { | ||
1110 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | ||
1111 | "request\n", dev->name); | ||
1112 | return; | 659 | return; |
1113 | } | ||
1114 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1115 | 660 | ||
1116 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 661 | buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + |
1117 | memset(mgmt, 0, 24); | 662 | ifsta->assocresp_ies_len), GFP_KERNEL); |
1118 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 663 | if (!buf) |
1119 | IEEE80211_STYPE_PROBE_REQ); | 664 | return; |
1120 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | ||
1121 | if (dst) { | ||
1122 | memcpy(mgmt->da, dst, ETH_ALEN); | ||
1123 | memcpy(mgmt->bssid, dst, ETH_ALEN); | ||
1124 | } else { | ||
1125 | memset(mgmt->da, 0xff, ETH_ALEN); | ||
1126 | memset(mgmt->bssid, 0xff, ETH_ALEN); | ||
1127 | } | ||
1128 | pos = skb_put(skb, 2 + ssid_len); | ||
1129 | *pos++ = WLAN_EID_SSID; | ||
1130 | *pos++ = ssid_len; | ||
1131 | memcpy(pos, ssid, ssid_len); | ||
1132 | |||
1133 | supp_rates = skb_put(skb, 2); | ||
1134 | supp_rates[0] = WLAN_EID_SUPP_RATES; | ||
1135 | supp_rates[1] = 0; | ||
1136 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1137 | 665 | ||
1138 | for (i = 0; i < sband->n_bitrates; i++) { | 666 | len = sprintf(buf, "ASSOCINFO("); |
1139 | struct ieee80211_rate *rate = &sband->bitrates[i]; | 667 | if (ifsta->assocreq_ies) { |
1140 | if (esupp_rates) { | 668 | len += sprintf(buf + len, "ReqIEs="); |
1141 | pos = skb_put(skb, 1); | 669 | for (i = 0; i < ifsta->assocreq_ies_len; i++) { |
1142 | esupp_rates[1]++; | 670 | len += sprintf(buf + len, "%02x", |
1143 | } else if (supp_rates[1] == 8) { | 671 | ifsta->assocreq_ies[i]); |
1144 | esupp_rates = skb_put(skb, 3); | ||
1145 | esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; | ||
1146 | esupp_rates[1] = 1; | ||
1147 | pos = &esupp_rates[2]; | ||
1148 | } else { | ||
1149 | pos = skb_put(skb, 1); | ||
1150 | supp_rates[1]++; | ||
1151 | } | 672 | } |
1152 | *pos = rate->bitrate / 5; | ||
1153 | } | 673 | } |
674 | if (ifsta->assocresp_ies) { | ||
675 | if (ifsta->assocreq_ies) | ||
676 | len += sprintf(buf + len, " "); | ||
677 | len += sprintf(buf + len, "RespIEs="); | ||
678 | for (i = 0; i < ifsta->assocresp_ies_len; i++) { | ||
679 | len += sprintf(buf + len, "%02x", | ||
680 | ifsta->assocresp_ies[i]); | ||
681 | } | ||
682 | } | ||
683 | len += sprintf(buf + len, ")"); | ||
1154 | 684 | ||
1155 | ieee80211_sta_tx(dev, skb, 0); | 685 | if (len > IW_CUSTOM_MAX) { |
1156 | } | 686 | len = sprintf(buf, "ASSOCRESPIE="); |
687 | for (i = 0; i < ifsta->assocresp_ies_len; i++) { | ||
688 | len += sprintf(buf + len, "%02x", | ||
689 | ifsta->assocresp_ies[i]); | ||
690 | } | ||
691 | } | ||
1157 | 692 | ||
693 | if (len <= IW_CUSTOM_MAX) { | ||
694 | memset(&wrqu, 0, sizeof(wrqu)); | ||
695 | wrqu.data.length = len; | ||
696 | wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); | ||
697 | } | ||
1158 | 698 | ||
1159 | static int ieee80211_sta_wep_configured(struct net_device *dev) | 699 | kfree(buf); |
1160 | { | ||
1161 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1162 | if (!sdata || !sdata->default_key || | ||
1163 | sdata->default_key->conf.alg != ALG_WEP) | ||
1164 | return 0; | ||
1165 | return 1; | ||
1166 | } | 700 | } |
1167 | 701 | ||
1168 | 702 | ||
1169 | static void ieee80211_auth_completed(struct net_device *dev, | 703 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
1170 | struct ieee80211_if_sta *ifsta) | 704 | struct ieee80211_if_sta *ifsta) |
1171 | { | 705 | { |
1172 | printk(KERN_DEBUG "%s: authenticated\n", dev->name); | 706 | struct ieee80211_local *local = sdata->local; |
1173 | ifsta->flags |= IEEE80211_STA_AUTHENTICATED; | 707 | struct ieee80211_conf *conf = &local_to_hw(local)->conf; |
1174 | ieee80211_associate(dev, ifsta); | 708 | u32 changed = BSS_CHANGED_ASSOC; |
1175 | } | ||
1176 | 709 | ||
710 | struct ieee80211_bss *bss; | ||
1177 | 711 | ||
1178 | static void ieee80211_auth_challenge(struct net_device *dev, | 712 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; |
1179 | struct ieee80211_if_sta *ifsta, | ||
1180 | struct ieee80211_mgmt *mgmt, | ||
1181 | size_t len) | ||
1182 | { | ||
1183 | u8 *pos; | ||
1184 | struct ieee802_11_elems elems; | ||
1185 | 713 | ||
1186 | pos = mgmt->u.auth.variable; | 714 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1187 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1188 | if (!elems.challenge) | ||
1189 | return; | 715 | return; |
1190 | ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2, | ||
1191 | elems.challenge_len + 2, 1); | ||
1192 | } | ||
1193 | 716 | ||
1194 | static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, | 717 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
1195 | u8 dialog_token, u16 status, u16 policy, | 718 | conf->channel->center_freq, |
1196 | u16 buf_size, u16 timeout) | 719 | ifsta->ssid, ifsta->ssid_len); |
1197 | { | 720 | if (bss) { |
1198 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 721 | /* set timing information */ |
1199 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 722 | sdata->bss_conf.beacon_int = bss->beacon_int; |
1200 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 723 | sdata->bss_conf.timestamp = bss->timestamp; |
1201 | struct sk_buff *skb; | 724 | sdata->bss_conf.dtim_period = bss->dtim_period; |
1202 | struct ieee80211_mgmt *mgmt; | ||
1203 | u16 capab; | ||
1204 | 725 | ||
1205 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 726 | changed |= ieee80211_handle_bss_capability(sdata, bss); |
1206 | 727 | ||
1207 | if (!skb) { | 728 | ieee80211_rx_bss_put(local, bss); |
1208 | printk(KERN_DEBUG "%s: failed to allocate buffer " | ||
1209 | "for addba resp frame\n", dev->name); | ||
1210 | return; | ||
1211 | } | 729 | } |
1212 | 730 | ||
1213 | skb_reserve(skb, local->hw.extra_tx_headroom); | 731 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { |
1214 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 732 | changed |= BSS_CHANGED_HT; |
1215 | memset(mgmt, 0, 24); | 733 | sdata->bss_conf.assoc_ht = 1; |
1216 | memcpy(mgmt->da, da, ETH_ALEN); | 734 | sdata->bss_conf.ht_conf = &conf->ht_conf; |
1217 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 735 | sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; |
1218 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) | 736 | } |
1219 | memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); | ||
1220 | else | ||
1221 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1222 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1223 | IEEE80211_STYPE_ACTION); | ||
1224 | 737 | ||
1225 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); | 738 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; |
1226 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | 739 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); |
1227 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | 740 | ieee80211_sta_send_associnfo(sdata, ifsta); |
1228 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | ||
1229 | 741 | ||
1230 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | 742 | ifsta->last_probe = jiffies; |
1231 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | 743 | ieee80211_led_assoc(local, 1); |
1232 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | ||
1233 | 744 | ||
1234 | mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); | 745 | sdata->bss_conf.assoc = 1; |
1235 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | 746 | /* |
1236 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | 747 | * For now just always ask the driver to update the basic rateset |
748 | * when we have associated, we aren't checking whether it actually | ||
749 | * changed or not. | ||
750 | */ | ||
751 | changed |= BSS_CHANGED_BASIC_RATES; | ||
752 | ieee80211_bss_info_change_notify(sdata, changed); | ||
1237 | 753 | ||
1238 | ieee80211_sta_tx(dev, skb, 0); | 754 | netif_tx_start_all_queues(sdata->dev); |
755 | netif_carrier_on(sdata->dev); | ||
1239 | 756 | ||
1240 | return; | 757 | ieee80211_sta_send_apinfo(sdata, ifsta); |
1241 | } | 758 | } |
1242 | 759 | ||
1243 | void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | 760 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, |
1244 | u16 tid, u8 dialog_token, u16 start_seq_num, | 761 | struct ieee80211_if_sta *ifsta) |
1245 | u16 agg_size, u16 timeout) | ||
1246 | { | 762 | { |
1247 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 763 | DECLARE_MAC_BUF(mac); |
1248 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1249 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1250 | struct sk_buff *skb; | ||
1251 | struct ieee80211_mgmt *mgmt; | ||
1252 | u16 capab; | ||
1253 | |||
1254 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
1255 | 764 | ||
1256 | if (!skb) { | 765 | ifsta->direct_probe_tries++; |
1257 | printk(KERN_ERR "%s: failed to allocate buffer " | 766 | if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { |
1258 | "for addba request frame\n", dev->name); | 767 | printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", |
768 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | ||
769 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1259 | return; | 770 | return; |
1260 | } | 771 | } |
1261 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1262 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
1263 | memset(mgmt, 0, 24); | ||
1264 | memcpy(mgmt->da, da, ETH_ALEN); | ||
1265 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | ||
1266 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) | ||
1267 | memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); | ||
1268 | else | ||
1269 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1270 | |||
1271 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1272 | IEEE80211_STYPE_ACTION); | ||
1273 | |||
1274 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); | ||
1275 | 772 | ||
1276 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | 773 | printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", |
1277 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | 774 | sdata->dev->name, print_mac(mac, ifsta->bssid), |
775 | ifsta->direct_probe_tries); | ||
1278 | 776 | ||
1279 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | 777 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
1280 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
1281 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
1282 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | ||
1283 | 778 | ||
1284 | mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); | 779 | set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); |
1285 | 780 | ||
1286 | mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); | 781 | /* Direct probe is sent to broadcast address as some APs |
1287 | mgmt->u.action.u.addba_req.start_seq_num = | 782 | * will not answer to direct packet in unassociated state. |
1288 | cpu_to_le16(start_seq_num << 4); | 783 | */ |
784 | ieee80211_send_probe_req(sdata, NULL, | ||
785 | ifsta->ssid, ifsta->ssid_len); | ||
1289 | 786 | ||
1290 | ieee80211_sta_tx(dev, skb, 0); | 787 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
1291 | } | 788 | } |
1292 | 789 | ||
1293 | static void ieee80211_sta_process_addba_request(struct net_device *dev, | 790 | |
1294 | struct ieee80211_mgmt *mgmt, | 791 | static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, |
1295 | size_t len) | 792 | struct ieee80211_if_sta *ifsta) |
1296 | { | 793 | { |
1297 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1298 | struct ieee80211_hw *hw = &local->hw; | ||
1299 | struct ieee80211_conf *conf = &hw->conf; | ||
1300 | struct sta_info *sta; | ||
1301 | struct tid_ampdu_rx *tid_agg_rx; | ||
1302 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | ||
1303 | u8 dialog_token; | ||
1304 | int ret = -EOPNOTSUPP; | ||
1305 | DECLARE_MAC_BUF(mac); | 794 | DECLARE_MAC_BUF(mac); |
1306 | 795 | ||
1307 | rcu_read_lock(); | 796 | ifsta->auth_tries++; |
1308 | 797 | if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | |
1309 | sta = sta_info_get(local, mgmt->sa); | 798 | printk(KERN_DEBUG "%s: authentication with AP %s" |
1310 | if (!sta) { | 799 | " timed out\n", |
1311 | rcu_read_unlock(); | 800 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
801 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1312 | return; | 802 | return; |
1313 | } | 803 | } |
1314 | 804 | ||
1315 | /* extract session parameters from addba request frame */ | 805 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; |
1316 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | 806 | printk(KERN_DEBUG "%s: authenticate with AP %s\n", |
1317 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | 807 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1318 | start_seq_num = | ||
1319 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
1320 | |||
1321 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
1322 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
1323 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
1324 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
1325 | |||
1326 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
1327 | |||
1328 | /* sanity check for incoming parameters: | ||
1329 | * check if configuration can support the BA policy | ||
1330 | * and if buffer size does not exceeds max value */ | ||
1331 | if (((ba_policy != 1) | ||
1332 | && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) | ||
1333 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | ||
1334 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
1335 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1336 | if (net_ratelimit()) | ||
1337 | printk(KERN_DEBUG "AddBA Req with bad params from " | ||
1338 | "%s on tid %u. policy %d, buffer size %d\n", | ||
1339 | print_mac(mac, mgmt->sa), tid, ba_policy, | ||
1340 | buf_size); | ||
1341 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1342 | goto end_no_lock; | ||
1343 | } | ||
1344 | /* determine default buffer size */ | ||
1345 | if (buf_size == 0) { | ||
1346 | struct ieee80211_supported_band *sband; | ||
1347 | |||
1348 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
1349 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
1350 | buf_size = buf_size << sband->ht_info.ampdu_factor; | ||
1351 | } | ||
1352 | |||
1353 | |||
1354 | /* examine state machine */ | ||
1355 | spin_lock_bh(&sta->lock); | ||
1356 | 808 | ||
1357 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 809 | ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); |
1358 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1359 | if (net_ratelimit()) | ||
1360 | printk(KERN_DEBUG "unexpected AddBA Req from " | ||
1361 | "%s on tid %u\n", | ||
1362 | print_mac(mac, mgmt->sa), tid); | ||
1363 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1364 | goto end; | ||
1365 | } | ||
1366 | 810 | ||
1367 | /* prepare A-MPDU MLME for Rx aggregation */ | 811 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
1368 | sta->ampdu_mlme.tid_rx[tid] = | ||
1369 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
1370 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
1371 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1372 | if (net_ratelimit()) | ||
1373 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
1374 | tid); | ||
1375 | #endif | ||
1376 | goto end; | ||
1377 | } | ||
1378 | /* rx timer */ | ||
1379 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
1380 | sta_rx_agg_session_timer_expired; | ||
1381 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
1382 | (unsigned long)&sta->timer_to_tid[tid]; | ||
1383 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
1384 | |||
1385 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
1386 | |||
1387 | /* prepare reordering buffer */ | ||
1388 | tid_agg_rx->reorder_buf = | ||
1389 | kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); | ||
1390 | if (!tid_agg_rx->reorder_buf) { | ||
1391 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1392 | if (net_ratelimit()) | ||
1393 | printk(KERN_ERR "can not allocate reordering buffer " | ||
1394 | "to tid %d\n", tid); | ||
1395 | #endif | ||
1396 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1397 | goto end; | ||
1398 | } | ||
1399 | memset(tid_agg_rx->reorder_buf, 0, | ||
1400 | buf_size * sizeof(struct sk_buff *)); | ||
1401 | |||
1402 | if (local->ops->ampdu_action) | ||
1403 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | ||
1404 | sta->addr, tid, &start_seq_num); | ||
1405 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1406 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
1407 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1408 | |||
1409 | if (ret) { | ||
1410 | kfree(tid_agg_rx->reorder_buf); | ||
1411 | kfree(tid_agg_rx); | ||
1412 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1413 | goto end; | ||
1414 | } | ||
1415 | |||
1416 | /* change state and send addba resp */ | ||
1417 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | ||
1418 | tid_agg_rx->dialog_token = dialog_token; | ||
1419 | tid_agg_rx->ssn = start_seq_num; | ||
1420 | tid_agg_rx->head_seq_num = start_seq_num; | ||
1421 | tid_agg_rx->buf_size = buf_size; | ||
1422 | tid_agg_rx->timeout = timeout; | ||
1423 | tid_agg_rx->stored_mpdu_num = 0; | ||
1424 | status = WLAN_STATUS_SUCCESS; | ||
1425 | end: | ||
1426 | spin_unlock_bh(&sta->lock); | ||
1427 | |||
1428 | end_no_lock: | ||
1429 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, | ||
1430 | dialog_token, status, 1, buf_size, timeout); | ||
1431 | rcu_read_unlock(); | ||
1432 | } | 812 | } |
1433 | 813 | ||
1434 | static void ieee80211_sta_process_addba_resp(struct net_device *dev, | 814 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
1435 | struct ieee80211_mgmt *mgmt, | 815 | struct ieee80211_if_sta *ifsta, bool deauth, |
1436 | size_t len) | 816 | bool self_disconnected, u16 reason) |
1437 | { | 817 | { |
1438 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 818 | struct ieee80211_local *local = sdata->local; |
1439 | struct ieee80211_hw *hw = &local->hw; | ||
1440 | struct sta_info *sta; | 819 | struct sta_info *sta; |
1441 | u16 capab; | 820 | u32 changed = BSS_CHANGED_ASSOC; |
1442 | u16 tid; | ||
1443 | u8 *state; | ||
1444 | 821 | ||
1445 | rcu_read_lock(); | 822 | rcu_read_lock(); |
1446 | 823 | ||
1447 | sta = sta_info_get(local, mgmt->sa); | 824 | sta = sta_info_get(local, ifsta->bssid); |
1448 | if (!sta) { | 825 | if (!sta) { |
1449 | rcu_read_unlock(); | 826 | rcu_read_unlock(); |
1450 | return; | 827 | return; |
1451 | } | 828 | } |
1452 | 829 | ||
1453 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 830 | if (deauth) { |
1454 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 831 | ifsta->direct_probe_tries = 0; |
832 | ifsta->auth_tries = 0; | ||
833 | } | ||
834 | ifsta->assoc_scan_tries = 0; | ||
835 | ifsta->assoc_tries = 0; | ||
1455 | 836 | ||
1456 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 837 | netif_tx_stop_all_queues(sdata->dev); |
838 | netif_carrier_off(sdata->dev); | ||
1457 | 839 | ||
1458 | spin_lock_bh(&sta->lock); | 840 | ieee80211_sta_tear_down_BA_sessions(sdata, sta->sta.addr); |
1459 | 841 | ||
1460 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 842 | if (self_disconnected) { |
1461 | spin_unlock_bh(&sta->lock); | 843 | if (deauth) |
1462 | goto addba_resp_exit; | 844 | ieee80211_send_deauth_disassoc(sdata, |
845 | IEEE80211_STYPE_DEAUTH, reason); | ||
846 | else | ||
847 | ieee80211_send_deauth_disassoc(sdata, | ||
848 | IEEE80211_STYPE_DISASSOC, reason); | ||
1463 | } | 849 | } |
1464 | 850 | ||
1465 | if (mgmt->u.action.u.addba_resp.dialog_token != | 851 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
1466 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | 852 | changed |= ieee80211_reset_erp_info(sdata); |
1467 | spin_unlock_bh(&sta->lock); | ||
1468 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1469 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
1470 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1471 | goto addba_resp_exit; | ||
1472 | } | ||
1473 | 853 | ||
1474 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 854 | if (sdata->bss_conf.assoc_ht) |
1475 | #ifdef CONFIG_MAC80211_HT_DEBUG | 855 | changed |= BSS_CHANGED_HT; |
1476 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | ||
1477 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1478 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | ||
1479 | == WLAN_STATUS_SUCCESS) { | ||
1480 | *state |= HT_ADDBA_RECEIVED_MSK; | ||
1481 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
1482 | 856 | ||
1483 | if (*state == HT_AGG_STATE_OPERATIONAL) | 857 | sdata->bss_conf.assoc_ht = 0; |
1484 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 858 | sdata->bss_conf.ht_conf = NULL; |
859 | sdata->bss_conf.ht_bss_conf = NULL; | ||
1485 | 860 | ||
1486 | spin_unlock_bh(&sta->lock); | 861 | ieee80211_led_assoc(local, 0); |
1487 | } else { | 862 | sdata->bss_conf.assoc = 0; |
1488 | sta->ampdu_mlme.addba_req_num[tid]++; | 863 | |
1489 | /* this will allow the state check in stop_BA_session */ | 864 | ieee80211_sta_send_apinfo(sdata, ifsta); |
1490 | *state = HT_AGG_STATE_OPERATIONAL; | 865 | |
1491 | spin_unlock_bh(&sta->lock); | 866 | if (self_disconnected) |
1492 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 867 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
1493 | WLAN_BACK_INITIATOR); | 868 | |
1494 | } | 869 | sta_info_unlink(&sta); |
1495 | 870 | ||
1496 | addba_resp_exit: | ||
1497 | rcu_read_unlock(); | 871 | rcu_read_unlock(); |
872 | |||
873 | sta_info_destroy(sta); | ||
1498 | } | 874 | } |
1499 | 875 | ||
1500 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | 876 | static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) |
1501 | u16 initiator, u16 reason_code) | ||
1502 | { | 877 | { |
1503 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 878 | if (!sdata || !sdata->default_key || |
1504 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 879 | sdata->default_key->conf.alg != ALG_WEP) |
1505 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 880 | return 0; |
1506 | struct sk_buff *skb; | 881 | return 1; |
1507 | struct ieee80211_mgmt *mgmt; | 882 | } |
1508 | u16 params; | ||
1509 | |||
1510 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
1511 | |||
1512 | if (!skb) { | ||
1513 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
1514 | "for delba frame\n", dev->name); | ||
1515 | return; | ||
1516 | } | ||
1517 | 883 | ||
1518 | skb_reserve(skb, local->hw.extra_tx_headroom); | 884 | static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, |
1519 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 885 | struct ieee80211_if_sta *ifsta) |
1520 | memset(mgmt, 0, 24); | 886 | { |
1521 | memcpy(mgmt->da, da, ETH_ALEN); | 887 | struct ieee80211_local *local = sdata->local; |
1522 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 888 | struct ieee80211_bss *bss; |
1523 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) | 889 | int bss_privacy; |
1524 | memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); | 890 | int wep_privacy; |
1525 | else | 891 | int privacy_invoked; |
1526 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1527 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1528 | IEEE80211_STYPE_ACTION); | ||
1529 | 892 | ||
1530 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); | 893 | if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) |
894 | return 0; | ||
1531 | 895 | ||
1532 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | 896 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
1533 | mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | 897 | local->hw.conf.channel->center_freq, |
1534 | params = (u16)(initiator << 11); /* bit 11 initiator */ | 898 | ifsta->ssid, ifsta->ssid_len); |
1535 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | 899 | if (!bss) |
900 | return 0; | ||
1536 | 901 | ||
1537 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 902 | bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); |
1538 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 903 | wep_privacy = !!ieee80211_sta_wep_configured(sdata); |
904 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | ||
1539 | 905 | ||
1540 | ieee80211_sta_tx(dev, skb, 0); | 906 | ieee80211_rx_bss_put(local, bss); |
1541 | } | ||
1542 | 907 | ||
1543 | void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) | 908 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) |
1544 | { | 909 | return 0; |
1545 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1546 | struct sk_buff *skb; | ||
1547 | struct ieee80211_bar *bar; | ||
1548 | u16 bar_control = 0; | ||
1549 | 910 | ||
1550 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | 911 | return 1; |
1551 | if (!skb) { | ||
1552 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
1553 | "bar frame\n", dev->name); | ||
1554 | return; | ||
1555 | } | ||
1556 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1557 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
1558 | memset(bar, 0, sizeof(*bar)); | ||
1559 | bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, | ||
1560 | IEEE80211_STYPE_BACK_REQ); | ||
1561 | memcpy(bar->ra, ra, ETH_ALEN); | ||
1562 | memcpy(bar->ta, dev->dev_addr, ETH_ALEN); | ||
1563 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
1564 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
1565 | bar_control |= (u16)(tid << 12); | ||
1566 | bar->control = cpu_to_le16(bar_control); | ||
1567 | bar->start_seq_num = cpu_to_le16(ssn); | ||
1568 | |||
1569 | ieee80211_sta_tx(dev, skb, 0); | ||
1570 | } | 912 | } |
1571 | 913 | ||
1572 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | 914 | static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, |
1573 | u16 initiator, u16 reason) | 915 | struct ieee80211_if_sta *ifsta) |
1574 | { | 916 | { |
1575 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1576 | struct ieee80211_hw *hw = &local->hw; | ||
1577 | struct sta_info *sta; | ||
1578 | int ret, i; | ||
1579 | DECLARE_MAC_BUF(mac); | 917 | DECLARE_MAC_BUF(mac); |
1580 | 918 | ||
1581 | rcu_read_lock(); | 919 | ifsta->assoc_tries++; |
1582 | 920 | if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { | |
1583 | sta = sta_info_get(local, ra); | 921 | printk(KERN_DEBUG "%s: association with AP %s" |
1584 | if (!sta) { | 922 | " timed out\n", |
1585 | rcu_read_unlock(); | 923 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
924 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1586 | return; | 925 | return; |
1587 | } | 926 | } |
1588 | 927 | ||
1589 | /* check if TID is in operational state */ | 928 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; |
1590 | spin_lock_bh(&sta->lock); | 929 | printk(KERN_DEBUG "%s: associate with AP %s\n", |
1591 | if (sta->ampdu_mlme.tid_state_rx[tid] | 930 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1592 | != HT_AGG_STATE_OPERATIONAL) { | 931 | if (ieee80211_privacy_mismatch(sdata, ifsta)) { |
1593 | spin_unlock_bh(&sta->lock); | 932 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " |
1594 | rcu_read_unlock(); | 933 | "mixed-cell disabled - abort association\n", sdata->dev->name); |
934 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1595 | return; | 935 | return; |
1596 | } | 936 | } |
1597 | sta->ampdu_mlme.tid_state_rx[tid] = | ||
1598 | HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
1599 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
1600 | spin_unlock_bh(&sta->lock); | ||
1601 | |||
1602 | /* stop HW Rx aggregation. ampdu_action existence | ||
1603 | * already verified in session init so we add the BUG_ON */ | ||
1604 | BUG_ON(!local->ops->ampdu_action); | ||
1605 | |||
1606 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1607 | printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", | ||
1608 | print_mac(mac, ra), tid); | ||
1609 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1610 | |||
1611 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | ||
1612 | ra, tid, NULL); | ||
1613 | if (ret) | ||
1614 | printk(KERN_DEBUG "HW problem - can not stop rx " | ||
1615 | "aggregation for tid %d\n", tid); | ||
1616 | |||
1617 | /* shutdown timer has not expired */ | ||
1618 | if (initiator != WLAN_BACK_TIMER) | ||
1619 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
1620 | |||
1621 | /* check if this is a self generated aggregation halt */ | ||
1622 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | ||
1623 | ieee80211_send_delba(dev, ra, tid, 0, reason); | ||
1624 | |||
1625 | /* free the reordering buffer */ | ||
1626 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | ||
1627 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | ||
1628 | /* release the reordered frames */ | ||
1629 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | ||
1630 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | ||
1631 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | ||
1632 | } | ||
1633 | } | ||
1634 | /* free resources */ | ||
1635 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
1636 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1637 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1638 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
1639 | 937 | ||
1640 | rcu_read_unlock(); | 938 | ieee80211_send_assoc(sdata, ifsta); |
939 | |||
940 | mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); | ||
1641 | } | 941 | } |
1642 | 942 | ||
1643 | 943 | ||
1644 | static void ieee80211_sta_process_delba(struct net_device *dev, | 944 | static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, |
1645 | struct ieee80211_mgmt *mgmt, size_t len) | 945 | struct ieee80211_if_sta *ifsta) |
1646 | { | 946 | { |
1647 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 947 | struct ieee80211_local *local = sdata->local; |
1648 | struct sta_info *sta; | 948 | struct sta_info *sta; |
1649 | u16 tid, params; | 949 | int disassoc; |
1650 | u16 initiator; | ||
1651 | DECLARE_MAC_BUF(mac); | 950 | DECLARE_MAC_BUF(mac); |
1652 | 951 | ||
1653 | rcu_read_lock(); | 952 | /* TODO: start monitoring current AP signal quality and number of |
1654 | 953 | * missed beacons. Scan other channels every now and then and search | |
1655 | sta = sta_info_get(local, mgmt->sa); | 954 | * for better APs. */ |
1656 | if (!sta) { | 955 | /* TODO: remove expired BSSes */ |
1657 | rcu_read_unlock(); | ||
1658 | return; | ||
1659 | } | ||
1660 | |||
1661 | params = le16_to_cpu(mgmt->u.action.u.delba.params); | ||
1662 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; | ||
1663 | initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11; | ||
1664 | |||
1665 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1666 | if (net_ratelimit()) | ||
1667 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", | ||
1668 | print_mac(mac, mgmt->sa), | ||
1669 | initiator ? "initiator" : "recipient", tid, | ||
1670 | mgmt->u.action.u.delba.reason_code); | ||
1671 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1672 | |||
1673 | if (initiator == WLAN_BACK_INITIATOR) | ||
1674 | ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, | ||
1675 | WLAN_BACK_INITIATOR, 0); | ||
1676 | else { /* WLAN_BACK_RECIPIENT */ | ||
1677 | spin_lock_bh(&sta->lock); | ||
1678 | sta->ampdu_mlme.tid_state_tx[tid] = | ||
1679 | HT_AGG_STATE_OPERATIONAL; | ||
1680 | spin_unlock_bh(&sta->lock); | ||
1681 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | ||
1682 | WLAN_BACK_RECIPIENT); | ||
1683 | } | ||
1684 | rcu_read_unlock(); | ||
1685 | } | ||
1686 | 956 | ||
1687 | /* | 957 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATED; |
1688 | * After sending add Block Ack request we activated a timer until | ||
1689 | * add Block Ack response will arrive from the recipient. | ||
1690 | * If this timer expires sta_addba_resp_timer_expired will be executed. | ||
1691 | */ | ||
1692 | void sta_addba_resp_timer_expired(unsigned long data) | ||
1693 | { | ||
1694 | /* not an elegant detour, but there is no choice as the timer passes | ||
1695 | * only one argument, and both sta_info and TID are needed, so init | ||
1696 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
1697 | * array gives the sta through container_of */ | ||
1698 | u16 tid = *(u8 *)data; | ||
1699 | struct sta_info *temp_sta = container_of((void *)data, | ||
1700 | struct sta_info, timer_to_tid[tid]); | ||
1701 | |||
1702 | struct ieee80211_local *local = temp_sta->local; | ||
1703 | struct ieee80211_hw *hw = &local->hw; | ||
1704 | struct sta_info *sta; | ||
1705 | u8 *state; | ||
1706 | 958 | ||
1707 | rcu_read_lock(); | 959 | rcu_read_lock(); |
1708 | 960 | ||
1709 | sta = sta_info_get(local, temp_sta->addr); | 961 | sta = sta_info_get(local, ifsta->bssid); |
1710 | if (!sta) { | 962 | if (!sta) { |
1711 | rcu_read_unlock(); | 963 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", |
1712 | return; | 964 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1713 | } | 965 | disassoc = 1; |
1714 | 966 | } else { | |
1715 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 967 | disassoc = 0; |
1716 | /* check if the TID waits for addBA response */ | 968 | if (time_after(jiffies, |
1717 | spin_lock_bh(&sta->lock); | 969 | sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { |
1718 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 970 | if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) { |
1719 | spin_unlock_bh(&sta->lock); | 971 | printk(KERN_DEBUG "%s: No ProbeResp from " |
1720 | *state = HT_AGG_STATE_IDLE; | 972 | "current AP %s - assume out of " |
1721 | #ifdef CONFIG_MAC80211_HT_DEBUG | 973 | "range\n", |
1722 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 974 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1723 | "expecting addBA response there", tid); | 975 | disassoc = 1; |
1724 | #endif | 976 | } else |
1725 | goto timer_expired_exit; | 977 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
978 | ifsta->ssid, | ||
979 | ifsta->ssid_len); | ||
980 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | ||
981 | } else { | ||
982 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | ||
983 | if (time_after(jiffies, ifsta->last_probe + | ||
984 | IEEE80211_PROBE_INTERVAL)) { | ||
985 | ifsta->last_probe = jiffies; | ||
986 | ieee80211_send_probe_req(sdata, ifsta->bssid, | ||
987 | ifsta->ssid, | ||
988 | ifsta->ssid_len); | ||
989 | } | ||
990 | } | ||
1726 | } | 991 | } |
1727 | 992 | ||
1728 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1729 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
1730 | #endif | ||
1731 | |||
1732 | /* go through the state check in stop_BA_session */ | ||
1733 | *state = HT_AGG_STATE_OPERATIONAL; | ||
1734 | spin_unlock_bh(&sta->lock); | ||
1735 | ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, | ||
1736 | WLAN_BACK_INITIATOR); | ||
1737 | |||
1738 | timer_expired_exit: | ||
1739 | rcu_read_unlock(); | 993 | rcu_read_unlock(); |
1740 | } | ||
1741 | 994 | ||
1742 | /* | 995 | if (disassoc) |
1743 | * After accepting the AddBA Request we activated a timer, | 996 | ieee80211_set_disassoc(sdata, ifsta, true, true, |
1744 | * resetting it after each frame that arrives from the originator. | 997 | WLAN_REASON_PREV_AUTH_NOT_VALID); |
1745 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | 998 | else |
1746 | */ | 999 | mod_timer(&ifsta->timer, jiffies + |
1747 | static void sta_rx_agg_session_timer_expired(unsigned long data) | 1000 | IEEE80211_MONITORING_INTERVAL); |
1748 | { | ||
1749 | /* not an elegant detour, but there is no choice as the timer passes | ||
1750 | * only one argument, and various sta_info are needed here, so init | ||
1751 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
1752 | * array gives the sta through container_of */ | ||
1753 | u8 *ptid = (u8 *)data; | ||
1754 | u8 *timer_to_id = ptid - *ptid; | ||
1755 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
1756 | timer_to_tid[0]); | ||
1757 | |||
1758 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1759 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | ||
1760 | #endif | ||
1761 | ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, | ||
1762 | (u16)*ptid, WLAN_BACK_TIMER, | ||
1763 | WLAN_REASON_QSTA_TIMEOUT); | ||
1764 | } | 1001 | } |
1765 | 1002 | ||
1766 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) | ||
1767 | { | ||
1768 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1769 | int i; | ||
1770 | 1003 | ||
1771 | for (i = 0; i < STA_TID_NUM; i++) { | 1004 | static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, |
1772 | ieee80211_stop_tx_ba_session(&local->hw, addr, i, | 1005 | struct ieee80211_if_sta *ifsta) |
1773 | WLAN_BACK_INITIATOR); | 1006 | { |
1774 | ieee80211_sta_stop_rx_ba_session(dev, addr, i, | 1007 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); |
1775 | WLAN_BACK_RECIPIENT, | 1008 | ifsta->flags |= IEEE80211_STA_AUTHENTICATED; |
1776 | WLAN_REASON_QSTA_LEAVE_QBSS); | 1009 | ieee80211_associate(sdata, ifsta); |
1777 | } | ||
1778 | } | 1010 | } |
1779 | 1011 | ||
1780 | static void ieee80211_send_refuse_measurement_request(struct net_device *dev, | ||
1781 | struct ieee80211_msrment_ie *request_ie, | ||
1782 | const u8 *da, const u8 *bssid, | ||
1783 | u8 dialog_token) | ||
1784 | { | ||
1785 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1786 | struct sk_buff *skb; | ||
1787 | struct ieee80211_mgmt *msr_report; | ||
1788 | 1012 | ||
1789 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | 1013 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, |
1790 | sizeof(struct ieee80211_msrment_ie)); | 1014 | struct ieee80211_if_sta *ifsta, |
1015 | struct ieee80211_mgmt *mgmt, | ||
1016 | size_t len) | ||
1017 | { | ||
1018 | u8 *pos; | ||
1019 | struct ieee802_11_elems elems; | ||
1791 | 1020 | ||
1792 | if (!skb) { | 1021 | pos = mgmt->u.auth.variable; |
1793 | printk(KERN_ERR "%s: failed to allocate buffer for " | 1022 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
1794 | "measurement report frame\n", dev->name); | 1023 | if (!elems.challenge) |
1795 | return; | 1024 | return; |
1796 | } | 1025 | ieee80211_send_auth(sdata, ifsta, 3, elems.challenge - 2, |
1797 | 1026 | elems.challenge_len + 2, 1); | |
1798 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1799 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | ||
1800 | memset(msr_report, 0, 24); | ||
1801 | memcpy(msr_report->da, da, ETH_ALEN); | ||
1802 | memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); | ||
1803 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | ||
1804 | msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1805 | IEEE80211_STYPE_ACTION); | ||
1806 | |||
1807 | skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); | ||
1808 | msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
1809 | msr_report->u.action.u.measurement.action_code = | ||
1810 | WLAN_ACTION_SPCT_MSR_RPRT; | ||
1811 | msr_report->u.action.u.measurement.dialog_token = dialog_token; | ||
1812 | |||
1813 | msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; | ||
1814 | msr_report->u.action.u.measurement.length = | ||
1815 | sizeof(struct ieee80211_msrment_ie); | ||
1816 | |||
1817 | memset(&msr_report->u.action.u.measurement.msr_elem, 0, | ||
1818 | sizeof(struct ieee80211_msrment_ie)); | ||
1819 | msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; | ||
1820 | msr_report->u.action.u.measurement.msr_elem.mode |= | ||
1821 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | ||
1822 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | ||
1823 | |||
1824 | ieee80211_sta_tx(dev, skb, 0); | ||
1825 | } | ||
1826 | |||
1827 | static void ieee80211_sta_process_measurement_req(struct net_device *dev, | ||
1828 | struct ieee80211_mgmt *mgmt, | ||
1829 | size_t len) | ||
1830 | { | ||
1831 | /* | ||
1832 | * Ignoring measurement request is spec violation. | ||
1833 | * Mandatory measurements must be reported optional | ||
1834 | * measurements might be refused or reported incapable | ||
1835 | * For now just refuse | ||
1836 | * TODO: Answer basic measurement as unmeasured | ||
1837 | */ | ||
1838 | ieee80211_send_refuse_measurement_request(dev, | ||
1839 | &mgmt->u.action.u.measurement.msr_elem, | ||
1840 | mgmt->sa, mgmt->bssid, | ||
1841 | mgmt->u.action.u.measurement.dialog_token); | ||
1842 | } | 1027 | } |
1843 | 1028 | ||
1844 | 1029 | static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |
1845 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, | ||
1846 | struct ieee80211_if_sta *ifsta, | 1030 | struct ieee80211_if_sta *ifsta, |
1847 | struct ieee80211_mgmt *mgmt, | 1031 | struct ieee80211_mgmt *mgmt, |
1848 | size_t len) | 1032 | size_t len) |
1849 | { | 1033 | { |
1850 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1851 | u16 auth_alg, auth_transaction, status_code; | 1034 | u16 auth_alg, auth_transaction, status_code; |
1852 | DECLARE_MAC_BUF(mac); | 1035 | DECLARE_MAC_BUF(mac); |
1853 | 1036 | ||
1854 | if (ifsta->state != IEEE80211_AUTHENTICATE && | 1037 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
1855 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | 1038 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1856 | return; | 1039 | return; |
1857 | 1040 | ||
1858 | if (len < 24 + 6) | 1041 | if (len < 24 + 6) |
1859 | return; | 1042 | return; |
1860 | 1043 | ||
1861 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1044 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
1862 | memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) | 1045 | memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) |
1863 | return; | 1046 | return; |
1864 | 1047 | ||
1865 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1048 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
1866 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) | 1049 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) |
1867 | return; | 1050 | return; |
1868 | 1051 | ||
@@ -1870,7 +1053,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1870 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | 1053 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); |
1871 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | 1054 | status_code = le16_to_cpu(mgmt->u.auth.status_code); |
1872 | 1055 | ||
1873 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1056 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1874 | /* | 1057 | /* |
1875 | * IEEE 802.11 standard does not require authentication in IBSS | 1058 | * IEEE 802.11 standard does not require authentication in IBSS |
1876 | * networks and most implementations do not seem to use it. | 1059 | * networks and most implementations do not seem to use it. |
@@ -1879,7 +1062,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1879 | */ | 1062 | */ |
1880 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | 1063 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) |
1881 | return; | 1064 | return; |
1882 | ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); | 1065 | ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); |
1883 | } | 1066 | } |
1884 | 1067 | ||
1885 | if (auth_alg != ifsta->auth_alg || | 1068 | if (auth_alg != ifsta->auth_alg || |
@@ -1912,7 +1095,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1912 | algs[pos] == 0xff) | 1095 | algs[pos] == 0xff) |
1913 | continue; | 1096 | continue; |
1914 | if (algs[pos] == WLAN_AUTH_SHARED_KEY && | 1097 | if (algs[pos] == WLAN_AUTH_SHARED_KEY && |
1915 | !ieee80211_sta_wep_configured(dev)) | 1098 | !ieee80211_sta_wep_configured(sdata)) |
1916 | continue; | 1099 | continue; |
1917 | ifsta->auth_alg = algs[pos]; | 1100 | ifsta->auth_alg = algs[pos]; |
1918 | break; | 1101 | break; |
@@ -1924,19 +1107,19 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1924 | switch (ifsta->auth_alg) { | 1107 | switch (ifsta->auth_alg) { |
1925 | case WLAN_AUTH_OPEN: | 1108 | case WLAN_AUTH_OPEN: |
1926 | case WLAN_AUTH_LEAP: | 1109 | case WLAN_AUTH_LEAP: |
1927 | ieee80211_auth_completed(dev, ifsta); | 1110 | ieee80211_auth_completed(sdata, ifsta); |
1928 | break; | 1111 | break; |
1929 | case WLAN_AUTH_SHARED_KEY: | 1112 | case WLAN_AUTH_SHARED_KEY: |
1930 | if (ifsta->auth_transaction == 4) | 1113 | if (ifsta->auth_transaction == 4) |
1931 | ieee80211_auth_completed(dev, ifsta); | 1114 | ieee80211_auth_completed(sdata, ifsta); |
1932 | else | 1115 | else |
1933 | ieee80211_auth_challenge(dev, ifsta, mgmt, len); | 1116 | ieee80211_auth_challenge(sdata, ifsta, mgmt, len); |
1934 | break; | 1117 | break; |
1935 | } | 1118 | } |
1936 | } | 1119 | } |
1937 | 1120 | ||
1938 | 1121 | ||
1939 | static void ieee80211_rx_mgmt_deauth(struct net_device *dev, | 1122 | static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
1940 | struct ieee80211_if_sta *ifsta, | 1123 | struct ieee80211_if_sta *ifsta, |
1941 | struct ieee80211_mgmt *mgmt, | 1124 | struct ieee80211_mgmt *mgmt, |
1942 | size_t len) | 1125 | size_t len) |
@@ -1953,22 +1136,22 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, | |||
1953 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1136 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1954 | 1137 | ||
1955 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) | 1138 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) |
1956 | printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); | 1139 | printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); |
1957 | 1140 | ||
1958 | if (ifsta->state == IEEE80211_AUTHENTICATE || | 1141 | if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || |
1959 | ifsta->state == IEEE80211_ASSOCIATE || | 1142 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || |
1960 | ifsta->state == IEEE80211_ASSOCIATED) { | 1143 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { |
1961 | ifsta->state = IEEE80211_AUTHENTICATE; | 1144 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
1962 | mod_timer(&ifsta->timer, jiffies + | 1145 | mod_timer(&ifsta->timer, jiffies + |
1963 | IEEE80211_RETRY_AUTH_INTERVAL); | 1146 | IEEE80211_RETRY_AUTH_INTERVAL); |
1964 | } | 1147 | } |
1965 | 1148 | ||
1966 | ieee80211_set_disassoc(dev, ifsta, 1); | 1149 | ieee80211_set_disassoc(sdata, ifsta, true, false, 0); |
1967 | ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; | 1150 | ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; |
1968 | } | 1151 | } |
1969 | 1152 | ||
1970 | 1153 | ||
1971 | static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, | 1154 | static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, |
1972 | struct ieee80211_if_sta *ifsta, | 1155 | struct ieee80211_if_sta *ifsta, |
1973 | struct ieee80211_mgmt *mgmt, | 1156 | struct ieee80211_mgmt *mgmt, |
1974 | size_t len) | 1157 | size_t len) |
@@ -1985,15 +1168,15 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, | |||
1985 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1168 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1986 | 1169 | ||
1987 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) | 1170 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) |
1988 | printk(KERN_DEBUG "%s: disassociated\n", dev->name); | 1171 | printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); |
1989 | 1172 | ||
1990 | if (ifsta->state == IEEE80211_ASSOCIATED) { | 1173 | if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { |
1991 | ifsta->state = IEEE80211_ASSOCIATE; | 1174 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; |
1992 | mod_timer(&ifsta->timer, jiffies + | 1175 | mod_timer(&ifsta->timer, jiffies + |
1993 | IEEE80211_RETRY_AUTH_INTERVAL); | 1176 | IEEE80211_RETRY_AUTH_INTERVAL); |
1994 | } | 1177 | } |
1995 | 1178 | ||
1996 | ieee80211_set_disassoc(dev, ifsta, 0); | 1179 | ieee80211_set_disassoc(sdata, ifsta, false, false, 0); |
1997 | } | 1180 | } |
1998 | 1181 | ||
1999 | 1182 | ||
@@ -2004,7 +1187,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2004 | int reassoc) | 1187 | int reassoc) |
2005 | { | 1188 | { |
2006 | struct ieee80211_local *local = sdata->local; | 1189 | struct ieee80211_local *local = sdata->local; |
2007 | struct net_device *dev = sdata->dev; | ||
2008 | struct ieee80211_supported_band *sband; | 1190 | struct ieee80211_supported_band *sband; |
2009 | struct sta_info *sta; | 1191 | struct sta_info *sta; |
2010 | u64 rates, basic_rates; | 1192 | u64 rates, basic_rates; |
@@ -2019,7 +1201,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2019 | /* AssocResp and ReassocResp have identical structure, so process both | 1201 | /* AssocResp and ReassocResp have identical structure, so process both |
2020 | * of them in this function. */ | 1202 | * of them in this function. */ |
2021 | 1203 | ||
2022 | if (ifsta->state != IEEE80211_ASSOCIATE) | 1204 | if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE) |
2023 | return; | 1205 | return; |
2024 | 1206 | ||
2025 | if (len < 24 + 6) | 1207 | if (len < 24 + 6) |
@@ -2034,12 +1216,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2034 | 1216 | ||
2035 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " | 1217 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " |
2036 | "status=%d aid=%d)\n", | 1218 | "status=%d aid=%d)\n", |
2037 | dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), | 1219 | sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), |
2038 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 1220 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
2039 | 1221 | ||
2040 | if (status_code != WLAN_STATUS_SUCCESS) { | 1222 | if (status_code != WLAN_STATUS_SUCCESS) { |
2041 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | 1223 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", |
2042 | dev->name, status_code); | 1224 | sdata->dev->name, status_code); |
2043 | /* if this was a reassociation, ensure we try a "full" | 1225 | /* if this was a reassociation, ensure we try a "full" |
2044 | * association next time. This works around some broken APs | 1226 | * association next time. This works around some broken APs |
2045 | * which do not correctly reject reassociation requests. */ | 1227 | * which do not correctly reject reassociation requests. */ |
@@ -2049,7 +1231,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2049 | 1231 | ||
2050 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1232 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
2051 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1233 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
2052 | "set\n", dev->name, aid); | 1234 | "set\n", sdata->dev->name, aid); |
2053 | aid &= ~(BIT(15) | BIT(14)); | 1235 | aid &= ~(BIT(15) | BIT(14)); |
2054 | 1236 | ||
2055 | pos = mgmt->u.assoc_resp.variable; | 1237 | pos = mgmt->u.assoc_resp.variable; |
@@ -2057,11 +1239,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2057 | 1239 | ||
2058 | if (!elems.supp_rates) { | 1240 | if (!elems.supp_rates) { |
2059 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1241 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
2060 | dev->name); | 1242 | sdata->dev->name); |
2061 | return; | 1243 | return; |
2062 | } | 1244 | } |
2063 | 1245 | ||
2064 | printk(KERN_DEBUG "%s: associated\n", dev->name); | 1246 | printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); |
2065 | ifsta->aid = aid; | 1247 | ifsta->aid = aid; |
2066 | ifsta->ap_capab = capab_info; | 1248 | ifsta->ap_capab = capab_info; |
2067 | 1249 | ||
@@ -2076,17 +1258,17 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2076 | /* Add STA entry for the AP */ | 1258 | /* Add STA entry for the AP */ |
2077 | sta = sta_info_get(local, ifsta->bssid); | 1259 | sta = sta_info_get(local, ifsta->bssid); |
2078 | if (!sta) { | 1260 | if (!sta) { |
2079 | struct ieee80211_sta_bss *bss; | 1261 | struct ieee80211_bss *bss; |
2080 | int err; | 1262 | int err; |
2081 | 1263 | ||
2082 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); | 1264 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); |
2083 | if (!sta) { | 1265 | if (!sta) { |
2084 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | 1266 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" |
2085 | " the AP\n", dev->name); | 1267 | " the AP\n", sdata->dev->name); |
2086 | rcu_read_unlock(); | 1268 | rcu_read_unlock(); |
2087 | return; | 1269 | return; |
2088 | } | 1270 | } |
2089 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 1271 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
2090 | local->hw.conf.channel->center_freq, | 1272 | local->hw.conf.channel->center_freq, |
2091 | ifsta->ssid, ifsta->ssid_len); | 1273 | ifsta->ssid, ifsta->ssid_len); |
2092 | if (bss) { | 1274 | if (bss) { |
@@ -2099,7 +1281,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2099 | err = sta_info_insert(sta); | 1281 | err = sta_info_insert(sta); |
2100 | if (err) { | 1282 | if (err) { |
2101 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 1283 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
2102 | " the AP (error %d)\n", dev->name, err); | 1284 | " the AP (error %d)\n", sdata->dev->name, err); |
2103 | rcu_read_unlock(); | 1285 | rcu_read_unlock(); |
2104 | return; | 1286 | return; |
2105 | } | 1287 | } |
@@ -2152,8 +1334,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2152 | } | 1334 | } |
2153 | } | 1335 | } |
2154 | 1336 | ||
2155 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 1337 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
2156 | sdata->basic_rates = basic_rates; | 1338 | sdata->bss_conf.basic_rates = basic_rates; |
2157 | 1339 | ||
2158 | /* cf. IEEE 802.11 9.2.12 */ | 1340 | /* cf. IEEE 802.11 9.2.12 */ |
2159 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 1341 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
@@ -2166,20 +1348,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2166 | (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | 1348 | (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { |
2167 | struct ieee80211_ht_bss_info bss_info; | 1349 | struct ieee80211_ht_bss_info bss_info; |
2168 | ieee80211_ht_cap_ie_to_ht_info( | 1350 | ieee80211_ht_cap_ie_to_ht_info( |
2169 | (struct ieee80211_ht_cap *) | 1351 | elems.ht_cap_elem, &sta->sta.ht_info); |
2170 | elems.ht_cap_elem, &sta->ht_info); | ||
2171 | ieee80211_ht_addt_info_ie_to_ht_bss_info( | 1352 | ieee80211_ht_addt_info_ie_to_ht_bss_info( |
2172 | (struct ieee80211_ht_addt_info *) | ||
2173 | elems.ht_info_elem, &bss_info); | 1353 | elems.ht_info_elem, &bss_info); |
2174 | ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info); | 1354 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); |
2175 | } | 1355 | } |
2176 | 1356 | ||
2177 | rate_control_rate_init(sta, local); | 1357 | rate_control_rate_init(sta); |
2178 | 1358 | ||
2179 | if (elems.wmm_param) { | 1359 | if (elems.wmm_param) { |
2180 | set_sta_flags(sta, WLAN_STA_WME); | 1360 | set_sta_flags(sta, WLAN_STA_WME); |
2181 | rcu_read_unlock(); | 1361 | rcu_read_unlock(); |
2182 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 1362 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
2183 | elems.wmm_param_len); | 1363 | elems.wmm_param_len); |
2184 | } else | 1364 | } else |
2185 | rcu_read_unlock(); | 1365 | rcu_read_unlock(); |
@@ -2188,234 +1368,26 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2188 | * ieee80211_set_associated() will tell the driver */ | 1368 | * ieee80211_set_associated() will tell the driver */ |
2189 | bss_conf->aid = aid; | 1369 | bss_conf->aid = aid; |
2190 | bss_conf->assoc_capability = capab_info; | 1370 | bss_conf->assoc_capability = capab_info; |
2191 | ieee80211_set_associated(dev, ifsta, 1); | 1371 | ieee80211_set_associated(sdata, ifsta); |
2192 | 1372 | ||
2193 | ieee80211_associated(dev, ifsta); | 1373 | ieee80211_associated(sdata, ifsta); |
2194 | } | 1374 | } |
2195 | 1375 | ||
2196 | 1376 | ||
2197 | /* Caller must hold local->sta_bss_lock */ | 1377 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
2198 | static void __ieee80211_rx_bss_hash_add(struct net_device *dev, | ||
2199 | struct ieee80211_sta_bss *bss) | ||
2200 | { | ||
2201 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2202 | u8 hash_idx; | ||
2203 | |||
2204 | if (bss_mesh_cfg(bss)) | ||
2205 | hash_idx = mesh_id_hash(bss_mesh_id(bss), | ||
2206 | bss_mesh_id_len(bss)); | ||
2207 | else | ||
2208 | hash_idx = STA_HASH(bss->bssid); | ||
2209 | |||
2210 | bss->hnext = local->sta_bss_hash[hash_idx]; | ||
2211 | local->sta_bss_hash[hash_idx] = bss; | ||
2212 | } | ||
2213 | |||
2214 | |||
2215 | /* Caller must hold local->sta_bss_lock */ | ||
2216 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, | ||
2217 | struct ieee80211_sta_bss *bss) | ||
2218 | { | ||
2219 | struct ieee80211_sta_bss *b, *prev = NULL; | ||
2220 | b = local->sta_bss_hash[STA_HASH(bss->bssid)]; | ||
2221 | while (b) { | ||
2222 | if (b == bss) { | ||
2223 | if (!prev) | ||
2224 | local->sta_bss_hash[STA_HASH(bss->bssid)] = | ||
2225 | bss->hnext; | ||
2226 | else | ||
2227 | prev->hnext = bss->hnext; | ||
2228 | break; | ||
2229 | } | ||
2230 | prev = b; | ||
2231 | b = b->hnext; | ||
2232 | } | ||
2233 | } | ||
2234 | |||
2235 | |||
2236 | static struct ieee80211_sta_bss * | ||
2237 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, | ||
2238 | u8 *ssid, u8 ssid_len) | ||
2239 | { | ||
2240 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2241 | struct ieee80211_sta_bss *bss; | ||
2242 | |||
2243 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
2244 | if (!bss) | ||
2245 | return NULL; | ||
2246 | atomic_inc(&bss->users); | ||
2247 | atomic_inc(&bss->users); | ||
2248 | memcpy(bss->bssid, bssid, ETH_ALEN); | ||
2249 | bss->freq = freq; | ||
2250 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
2251 | memcpy(bss->ssid, ssid, ssid_len); | ||
2252 | bss->ssid_len = ssid_len; | ||
2253 | } | ||
2254 | |||
2255 | spin_lock_bh(&local->sta_bss_lock); | ||
2256 | /* TODO: order by RSSI? */ | ||
2257 | list_add_tail(&bss->list, &local->sta_bss_list); | ||
2258 | __ieee80211_rx_bss_hash_add(dev, bss); | ||
2259 | spin_unlock_bh(&local->sta_bss_lock); | ||
2260 | return bss; | ||
2261 | } | ||
2262 | |||
2263 | static struct ieee80211_sta_bss * | ||
2264 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, | ||
2265 | u8 *ssid, u8 ssid_len) | ||
2266 | { | ||
2267 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2268 | struct ieee80211_sta_bss *bss; | ||
2269 | |||
2270 | spin_lock_bh(&local->sta_bss_lock); | ||
2271 | bss = local->sta_bss_hash[STA_HASH(bssid)]; | ||
2272 | while (bss) { | ||
2273 | if (!bss_mesh_cfg(bss) && | ||
2274 | !memcmp(bss->bssid, bssid, ETH_ALEN) && | ||
2275 | bss->freq == freq && | ||
2276 | bss->ssid_len == ssid_len && | ||
2277 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
2278 | atomic_inc(&bss->users); | ||
2279 | break; | ||
2280 | } | ||
2281 | bss = bss->hnext; | ||
2282 | } | ||
2283 | spin_unlock_bh(&local->sta_bss_lock); | ||
2284 | return bss; | ||
2285 | } | ||
2286 | |||
2287 | #ifdef CONFIG_MAC80211_MESH | ||
2288 | static struct ieee80211_sta_bss * | ||
2289 | ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, | ||
2290 | u8 *mesh_cfg, int freq) | ||
2291 | { | ||
2292 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2293 | struct ieee80211_sta_bss *bss; | ||
2294 | |||
2295 | spin_lock_bh(&local->sta_bss_lock); | ||
2296 | bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; | ||
2297 | while (bss) { | ||
2298 | if (bss_mesh_cfg(bss) && | ||
2299 | !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && | ||
2300 | bss->freq == freq && | ||
2301 | mesh_id_len == bss->mesh_id_len && | ||
2302 | (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, | ||
2303 | mesh_id_len))) { | ||
2304 | atomic_inc(&bss->users); | ||
2305 | break; | ||
2306 | } | ||
2307 | bss = bss->hnext; | ||
2308 | } | ||
2309 | spin_unlock_bh(&local->sta_bss_lock); | ||
2310 | return bss; | ||
2311 | } | ||
2312 | |||
2313 | static struct ieee80211_sta_bss * | ||
2314 | ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, | ||
2315 | u8 *mesh_cfg, int mesh_config_len, int freq) | ||
2316 | { | ||
2317 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2318 | struct ieee80211_sta_bss *bss; | ||
2319 | |||
2320 | if (mesh_config_len != MESH_CFG_LEN) | ||
2321 | return NULL; | ||
2322 | |||
2323 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
2324 | if (!bss) | ||
2325 | return NULL; | ||
2326 | |||
2327 | bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); | ||
2328 | if (!bss->mesh_cfg) { | ||
2329 | kfree(bss); | ||
2330 | return NULL; | ||
2331 | } | ||
2332 | |||
2333 | if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { | ||
2334 | bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); | ||
2335 | if (!bss->mesh_id) { | ||
2336 | kfree(bss->mesh_cfg); | ||
2337 | kfree(bss); | ||
2338 | return NULL; | ||
2339 | } | ||
2340 | memcpy(bss->mesh_id, mesh_id, mesh_id_len); | ||
2341 | } | ||
2342 | |||
2343 | atomic_inc(&bss->users); | ||
2344 | atomic_inc(&bss->users); | ||
2345 | memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); | ||
2346 | bss->mesh_id_len = mesh_id_len; | ||
2347 | bss->freq = freq; | ||
2348 | spin_lock_bh(&local->sta_bss_lock); | ||
2349 | /* TODO: order by RSSI? */ | ||
2350 | list_add_tail(&bss->list, &local->sta_bss_list); | ||
2351 | __ieee80211_rx_bss_hash_add(dev, bss); | ||
2352 | spin_unlock_bh(&local->sta_bss_lock); | ||
2353 | return bss; | ||
2354 | } | ||
2355 | #endif | ||
2356 | |||
2357 | static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) | ||
2358 | { | ||
2359 | kfree(bss->wpa_ie); | ||
2360 | kfree(bss->rsn_ie); | ||
2361 | kfree(bss->wmm_ie); | ||
2362 | kfree(bss->ht_ie); | ||
2363 | kfree(bss->ht_add_ie); | ||
2364 | kfree(bss_mesh_id(bss)); | ||
2365 | kfree(bss_mesh_cfg(bss)); | ||
2366 | kfree(bss); | ||
2367 | } | ||
2368 | |||
2369 | |||
2370 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
2371 | struct ieee80211_sta_bss *bss) | ||
2372 | { | ||
2373 | local_bh_disable(); | ||
2374 | if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { | ||
2375 | local_bh_enable(); | ||
2376 | return; | ||
2377 | } | ||
2378 | |||
2379 | __ieee80211_rx_bss_hash_del(local, bss); | ||
2380 | list_del(&bss->list); | ||
2381 | spin_unlock_bh(&local->sta_bss_lock); | ||
2382 | ieee80211_rx_bss_free(bss); | ||
2383 | } | ||
2384 | |||
2385 | |||
2386 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) | ||
2387 | { | ||
2388 | spin_lock_init(&local->sta_bss_lock); | ||
2389 | INIT_LIST_HEAD(&local->sta_bss_list); | ||
2390 | } | ||
2391 | |||
2392 | |||
2393 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) | ||
2394 | { | ||
2395 | struct ieee80211_sta_bss *bss, *tmp; | ||
2396 | |||
2397 | list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) | ||
2398 | ieee80211_rx_bss_put(local, bss); | ||
2399 | } | ||
2400 | |||
2401 | |||
2402 | static int ieee80211_sta_join_ibss(struct net_device *dev, | ||
2403 | struct ieee80211_if_sta *ifsta, | 1378 | struct ieee80211_if_sta *ifsta, |
2404 | struct ieee80211_sta_bss *bss) | 1379 | struct ieee80211_bss *bss) |
2405 | { | 1380 | { |
2406 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1381 | struct ieee80211_local *local = sdata->local; |
2407 | int res, rates, i, j; | 1382 | int res, rates, i, j; |
2408 | struct sk_buff *skb; | 1383 | struct sk_buff *skb; |
2409 | struct ieee80211_mgmt *mgmt; | 1384 | struct ieee80211_mgmt *mgmt; |
2410 | u8 *pos; | 1385 | u8 *pos; |
2411 | struct ieee80211_sub_if_data *sdata; | ||
2412 | struct ieee80211_supported_band *sband; | 1386 | struct ieee80211_supported_band *sband; |
2413 | union iwreq_data wrqu; | 1387 | union iwreq_data wrqu; |
2414 | 1388 | ||
2415 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1389 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2416 | 1390 | ||
2417 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2418 | |||
2419 | /* Remove possible STA entries from other IBSS networks. */ | 1391 | /* Remove possible STA entries from other IBSS networks. */ |
2420 | sta_info_flush_delayed(sdata); | 1392 | sta_info_flush_delayed(sdata); |
2421 | 1393 | ||
@@ -2433,7 +1405,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2433 | sdata->drop_unencrypted = bss->capability & | 1405 | sdata->drop_unencrypted = bss->capability & |
2434 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 1406 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
2435 | 1407 | ||
2436 | res = ieee80211_set_freq(dev, bss->freq); | 1408 | res = ieee80211_set_freq(sdata, bss->freq); |
2437 | 1409 | ||
2438 | if (res) | 1410 | if (res) |
2439 | return res; | 1411 | return res; |
@@ -2446,10 +1418,10 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2446 | mgmt = (struct ieee80211_mgmt *) | 1418 | mgmt = (struct ieee80211_mgmt *) |
2447 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1419 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
2448 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1420 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
2449 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 1421 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2450 | IEEE80211_STYPE_PROBE_RESP); | 1422 | IEEE80211_STYPE_PROBE_RESP); |
2451 | memset(mgmt->da, 0xff, ETH_ALEN); | 1423 | memset(mgmt->da, 0xff, ETH_ALEN); |
2452 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 1424 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
2453 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 1425 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
2454 | mgmt->u.beacon.beacon_int = | 1426 | mgmt->u.beacon.beacon_int = |
2455 | cpu_to_le16(local->hw.conf.beacon_int); | 1427 | cpu_to_le16(local->hw.conf.beacon_int); |
@@ -2506,108 +1478,38 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2506 | } | 1478 | } |
2507 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | 1479 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; |
2508 | 1480 | ||
2509 | ieee80211_sta_def_wmm_params(dev, bss, 1); | 1481 | ieee80211_sta_def_wmm_params(sdata, bss); |
2510 | 1482 | ||
2511 | ifsta->state = IEEE80211_IBSS_JOINED; | 1483 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
2512 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1484 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
2513 | 1485 | ||
1486 | ieee80211_led_assoc(local, true); | ||
1487 | |||
2514 | memset(&wrqu, 0, sizeof(wrqu)); | 1488 | memset(&wrqu, 0, sizeof(wrqu)); |
2515 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1489 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
2516 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 1490 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
2517 | 1491 | ||
2518 | return res; | 1492 | return res; |
2519 | } | 1493 | } |
2520 | 1494 | ||
2521 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1495 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
2522 | struct ieee802_11_elems *elems, | ||
2523 | enum ieee80211_band band) | ||
2524 | { | ||
2525 | struct ieee80211_supported_band *sband; | ||
2526 | struct ieee80211_rate *bitrates; | ||
2527 | size_t num_rates; | ||
2528 | u64 supp_rates; | ||
2529 | int i, j; | ||
2530 | sband = local->hw.wiphy->bands[band]; | ||
2531 | |||
2532 | if (!sband) { | ||
2533 | WARN_ON(1); | ||
2534 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2535 | } | ||
2536 | |||
2537 | bitrates = sband->bitrates; | ||
2538 | num_rates = sband->n_bitrates; | ||
2539 | supp_rates = 0; | ||
2540 | for (i = 0; i < elems->supp_rates_len + | ||
2541 | elems->ext_supp_rates_len; i++) { | ||
2542 | u8 rate = 0; | ||
2543 | int own_rate; | ||
2544 | if (i < elems->supp_rates_len) | ||
2545 | rate = elems->supp_rates[i]; | ||
2546 | else if (elems->ext_supp_rates) | ||
2547 | rate = elems->ext_supp_rates | ||
2548 | [i - elems->supp_rates_len]; | ||
2549 | own_rate = 5 * (rate & 0x7f); | ||
2550 | for (j = 0; j < num_rates; j++) | ||
2551 | if (bitrates[j].bitrate == own_rate) | ||
2552 | supp_rates |= BIT(j); | ||
2553 | } | ||
2554 | return supp_rates; | ||
2555 | } | ||
2556 | |||
2557 | |||
2558 | static void ieee80211_rx_bss_info(struct net_device *dev, | ||
2559 | struct ieee80211_mgmt *mgmt, | 1496 | struct ieee80211_mgmt *mgmt, |
2560 | size_t len, | 1497 | size_t len, |
2561 | struct ieee80211_rx_status *rx_status, | 1498 | struct ieee80211_rx_status *rx_status, |
2562 | struct ieee802_11_elems *elems, | 1499 | struct ieee802_11_elems *elems, |
2563 | int beacon) | 1500 | bool beacon) |
2564 | { | 1501 | { |
2565 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1502 | struct ieee80211_local *local = sdata->local; |
2566 | int freq, clen; | 1503 | int freq; |
2567 | struct ieee80211_sta_bss *bss; | 1504 | struct ieee80211_bss *bss; |
2568 | struct sta_info *sta; | 1505 | struct sta_info *sta; |
2569 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2570 | u64 beacon_timestamp, rx_timestamp; | ||
2571 | struct ieee80211_channel *channel; | 1506 | struct ieee80211_channel *channel; |
1507 | u64 beacon_timestamp, rx_timestamp; | ||
1508 | u64 supp_rates = 0; | ||
1509 | enum ieee80211_band band = rx_status->band; | ||
2572 | DECLARE_MAC_BUF(mac); | 1510 | DECLARE_MAC_BUF(mac); |
2573 | DECLARE_MAC_BUF(mac2); | 1511 | DECLARE_MAC_BUF(mac2); |
2574 | 1512 | ||
2575 | if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN)) | ||
2576 | return; /* ignore ProbeResp to foreign address */ | ||
2577 | |||
2578 | beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); | ||
2579 | |||
2580 | if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && | ||
2581 | elems->mesh_config && mesh_matches_local(elems, dev)) { | ||
2582 | u64 rates = ieee80211_sta_get_rates(local, elems, | ||
2583 | rx_status->band); | ||
2584 | |||
2585 | mesh_neighbour_update(mgmt->sa, rates, dev, | ||
2586 | mesh_peer_accepts_plinks(elems, dev)); | ||
2587 | } | ||
2588 | |||
2589 | rcu_read_lock(); | ||
2590 | |||
2591 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && | ||
2592 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && | ||
2593 | (sta = sta_info_get(local, mgmt->sa))) { | ||
2594 | u64 prev_rates; | ||
2595 | u64 supp_rates = ieee80211_sta_get_rates(local, elems, | ||
2596 | rx_status->band); | ||
2597 | |||
2598 | prev_rates = sta->supp_rates[rx_status->band]; | ||
2599 | sta->supp_rates[rx_status->band] &= supp_rates; | ||
2600 | if (sta->supp_rates[rx_status->band] == 0) { | ||
2601 | /* No matching rates - this should not really happen. | ||
2602 | * Make sure that at least one rate is marked | ||
2603 | * supported to avoid issues with TX rate ctrl. */ | ||
2604 | sta->supp_rates[rx_status->band] = | ||
2605 | sdata->u.sta.supp_rates_bits[rx_status->band]; | ||
2606 | } | ||
2607 | } | ||
2608 | |||
2609 | rcu_read_unlock(); | ||
2610 | |||
2611 | if (elems->ds_params && elems->ds_params_len == 1) | 1513 | if (elems->ds_params && elems->ds_params_len == 1) |
2612 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1514 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); |
2613 | else | 1515 | else |
@@ -2618,215 +1520,60 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2618 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 1520 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
2619 | return; | 1521 | return; |
2620 | 1522 | ||
2621 | #ifdef CONFIG_MAC80211_MESH | 1523 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates && |
2622 | if (elems->mesh_config) | 1524 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { |
2623 | bss = ieee80211_rx_mesh_bss_get(dev, elems->mesh_id, | 1525 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
2624 | elems->mesh_id_len, elems->mesh_config, freq); | ||
2625 | else | ||
2626 | #endif | ||
2627 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, | ||
2628 | elems->ssid, elems->ssid_len); | ||
2629 | if (!bss) { | ||
2630 | #ifdef CONFIG_MAC80211_MESH | ||
2631 | if (elems->mesh_config) | ||
2632 | bss = ieee80211_rx_mesh_bss_add(dev, elems->mesh_id, | ||
2633 | elems->mesh_id_len, elems->mesh_config, | ||
2634 | elems->mesh_config_len, freq); | ||
2635 | else | ||
2636 | #endif | ||
2637 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, | ||
2638 | elems->ssid, elems->ssid_len); | ||
2639 | if (!bss) | ||
2640 | return; | ||
2641 | } else { | ||
2642 | #if 0 | ||
2643 | /* TODO: order by RSSI? */ | ||
2644 | spin_lock_bh(&local->sta_bss_lock); | ||
2645 | list_move_tail(&bss->list, &local->sta_bss_list); | ||
2646 | spin_unlock_bh(&local->sta_bss_lock); | ||
2647 | #endif | ||
2648 | } | ||
2649 | |||
2650 | /* save the ERP value so that it is available at association time */ | ||
2651 | if (elems->erp_info && elems->erp_info_len >= 1) { | ||
2652 | bss->erp_value = elems->erp_info[0]; | ||
2653 | bss->has_erp_value = 1; | ||
2654 | } | ||
2655 | 1526 | ||
2656 | if (elems->ht_cap_elem && | 1527 | rcu_read_lock(); |
2657 | (!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len || | ||
2658 | memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) { | ||
2659 | kfree(bss->ht_ie); | ||
2660 | bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC); | ||
2661 | if (bss->ht_ie) { | ||
2662 | memcpy(bss->ht_ie, elems->ht_cap_elem - 2, | ||
2663 | elems->ht_cap_elem_len + 2); | ||
2664 | bss->ht_ie_len = elems->ht_cap_elem_len + 2; | ||
2665 | } else | ||
2666 | bss->ht_ie_len = 0; | ||
2667 | } else if (!elems->ht_cap_elem && bss->ht_ie) { | ||
2668 | kfree(bss->ht_ie); | ||
2669 | bss->ht_ie = NULL; | ||
2670 | bss->ht_ie_len = 0; | ||
2671 | } | ||
2672 | 1528 | ||
2673 | if (elems->ht_info_elem && | 1529 | sta = sta_info_get(local, mgmt->sa); |
2674 | (!bss->ht_add_ie || | 1530 | if (sta) { |
2675 | bss->ht_add_ie_len != elems->ht_info_elem_len || | 1531 | u64 prev_rates; |
2676 | memcmp(bss->ht_add_ie, elems->ht_info_elem, | ||
2677 | elems->ht_info_elem_len))) { | ||
2678 | kfree(bss->ht_add_ie); | ||
2679 | bss->ht_add_ie = | ||
2680 | kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC); | ||
2681 | if (bss->ht_add_ie) { | ||
2682 | memcpy(bss->ht_add_ie, elems->ht_info_elem - 2, | ||
2683 | elems->ht_info_elem_len + 2); | ||
2684 | bss->ht_add_ie_len = elems->ht_info_elem_len + 2; | ||
2685 | } else | ||
2686 | bss->ht_add_ie_len = 0; | ||
2687 | } else if (!elems->ht_info_elem && bss->ht_add_ie) { | ||
2688 | kfree(bss->ht_add_ie); | ||
2689 | bss->ht_add_ie = NULL; | ||
2690 | bss->ht_add_ie_len = 0; | ||
2691 | } | ||
2692 | 1532 | ||
2693 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 1533 | prev_rates = sta->sta.supp_rates[band]; |
2694 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 1534 | /* make sure mandatory rates are always added */ |
1535 | sta->sta.supp_rates[band] = supp_rates | | ||
1536 | ieee80211_mandatory_rates(local, band); | ||
2695 | 1537 | ||
2696 | if (elems->tim) { | 1538 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2697 | struct ieee80211_tim_ie *tim_ie = | 1539 | if (sta->sta.supp_rates[band] != prev_rates) |
2698 | (struct ieee80211_tim_ie *)elems->tim; | 1540 | printk(KERN_DEBUG "%s: updated supp_rates set " |
2699 | bss->dtim_period = tim_ie->dtim_period; | 1541 | "for %s based on beacon info (0x%llx | " |
2700 | } | 1542 | "0x%llx -> 0x%llx)\n", |
1543 | sdata->dev->name, | ||
1544 | print_mac(mac, sta->sta.addr), | ||
1545 | (unsigned long long) prev_rates, | ||
1546 | (unsigned long long) supp_rates, | ||
1547 | (unsigned long long) sta->sta.supp_rates[band]); | ||
1548 | #endif | ||
1549 | } else { | ||
1550 | ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, | ||
1551 | mgmt->sa, supp_rates); | ||
1552 | } | ||
2701 | 1553 | ||
2702 | /* set default value for buggy APs */ | 1554 | rcu_read_unlock(); |
2703 | if (!elems->tim || bss->dtim_period == 0) | ||
2704 | bss->dtim_period = 1; | ||
2705 | |||
2706 | bss->supp_rates_len = 0; | ||
2707 | if (elems->supp_rates) { | ||
2708 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
2709 | if (clen > elems->supp_rates_len) | ||
2710 | clen = elems->supp_rates_len; | ||
2711 | memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, | ||
2712 | clen); | ||
2713 | bss->supp_rates_len += clen; | ||
2714 | } | ||
2715 | if (elems->ext_supp_rates) { | ||
2716 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
2717 | if (clen > elems->ext_supp_rates_len) | ||
2718 | clen = elems->ext_supp_rates_len; | ||
2719 | memcpy(&bss->supp_rates[bss->supp_rates_len], | ||
2720 | elems->ext_supp_rates, clen); | ||
2721 | bss->supp_rates_len += clen; | ||
2722 | } | 1555 | } |
2723 | 1556 | ||
2724 | bss->band = rx_status->band; | 1557 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
1558 | freq, beacon); | ||
1559 | if (!bss) | ||
1560 | return; | ||
2725 | 1561 | ||
2726 | bss->timestamp = beacon_timestamp; | 1562 | /* was just updated in ieee80211_bss_info_update */ |
2727 | bss->last_update = jiffies; | 1563 | beacon_timestamp = bss->timestamp; |
2728 | bss->signal = rx_status->signal; | ||
2729 | bss->noise = rx_status->noise; | ||
2730 | bss->qual = rx_status->qual; | ||
2731 | if (!beacon && !bss->probe_resp) | ||
2732 | bss->probe_resp = true; | ||
2733 | 1564 | ||
2734 | /* | 1565 | /* |
2735 | * In STA mode, the remaining parameters should not be overridden | 1566 | * In STA mode, the remaining parameters should not be overridden |
2736 | * by beacons because they're not necessarily accurate there. | 1567 | * by beacons because they're not necessarily accurate there. |
2737 | */ | 1568 | */ |
2738 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1569 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2739 | bss->probe_resp && beacon) { | 1570 | bss->last_probe_resp && beacon) { |
2740 | ieee80211_rx_bss_put(local, bss); | 1571 | ieee80211_rx_bss_put(local, bss); |
2741 | return; | 1572 | return; |
2742 | } | 1573 | } |
2743 | 1574 | ||
2744 | if (elems->wpa && | ||
2745 | (!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len || | ||
2746 | memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) { | ||
2747 | kfree(bss->wpa_ie); | ||
2748 | bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC); | ||
2749 | if (bss->wpa_ie) { | ||
2750 | memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2); | ||
2751 | bss->wpa_ie_len = elems->wpa_len + 2; | ||
2752 | } else | ||
2753 | bss->wpa_ie_len = 0; | ||
2754 | } else if (!elems->wpa && bss->wpa_ie) { | ||
2755 | kfree(bss->wpa_ie); | ||
2756 | bss->wpa_ie = NULL; | ||
2757 | bss->wpa_ie_len = 0; | ||
2758 | } | ||
2759 | |||
2760 | if (elems->rsn && | ||
2761 | (!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len || | ||
2762 | memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) { | ||
2763 | kfree(bss->rsn_ie); | ||
2764 | bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC); | ||
2765 | if (bss->rsn_ie) { | ||
2766 | memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2); | ||
2767 | bss->rsn_ie_len = elems->rsn_len + 2; | ||
2768 | } else | ||
2769 | bss->rsn_ie_len = 0; | ||
2770 | } else if (!elems->rsn && bss->rsn_ie) { | ||
2771 | kfree(bss->rsn_ie); | ||
2772 | bss->rsn_ie = NULL; | ||
2773 | bss->rsn_ie_len = 0; | ||
2774 | } | ||
2775 | |||
2776 | /* | ||
2777 | * Cf. | ||
2778 | * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC | ||
2779 | * | ||
2780 | * quoting: | ||
2781 | * | ||
2782 | * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia | ||
2783 | * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi | ||
2784 | * Alliance (September 1, 2004) is incorporated by reference herein. | ||
2785 | * The inclusion of the WMM Parameters in probe responses and | ||
2786 | * association responses is mandatory for WMM enabled networks. The | ||
2787 | * inclusion of the WMM Parameters in beacons, however, is optional. | ||
2788 | */ | ||
2789 | |||
2790 | if (elems->wmm_param && | ||
2791 | (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len || | ||
2792 | memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) { | ||
2793 | kfree(bss->wmm_ie); | ||
2794 | bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC); | ||
2795 | if (bss->wmm_ie) { | ||
2796 | memcpy(bss->wmm_ie, elems->wmm_param - 2, | ||
2797 | elems->wmm_param_len + 2); | ||
2798 | bss->wmm_ie_len = elems->wmm_param_len + 2; | ||
2799 | } else | ||
2800 | bss->wmm_ie_len = 0; | ||
2801 | } else if (elems->wmm_info && | ||
2802 | (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len || | ||
2803 | memcmp(bss->wmm_ie, elems->wmm_info, | ||
2804 | elems->wmm_info_len))) { | ||
2805 | /* As for certain AP's Fifth bit is not set in WMM IE in | ||
2806 | * beacon frames.So while parsing the beacon frame the | ||
2807 | * wmm_info structure is used instead of wmm_param. | ||
2808 | * wmm_info structure was never used to set bss->wmm_ie. | ||
2809 | * This code fixes this problem by copying the WME | ||
2810 | * information from wmm_info to bss->wmm_ie and enabling | ||
2811 | * n-band association. | ||
2812 | */ | ||
2813 | kfree(bss->wmm_ie); | ||
2814 | bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC); | ||
2815 | if (bss->wmm_ie) { | ||
2816 | memcpy(bss->wmm_ie, elems->wmm_info - 2, | ||
2817 | elems->wmm_info_len + 2); | ||
2818 | bss->wmm_ie_len = elems->wmm_info_len + 2; | ||
2819 | } else | ||
2820 | bss->wmm_ie_len = 0; | ||
2821 | } else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) { | ||
2822 | kfree(bss->wmm_ie); | ||
2823 | bss->wmm_ie = NULL; | ||
2824 | bss->wmm_ie_len = 0; | ||
2825 | } | ||
2826 | |||
2827 | /* check if we need to merge IBSS */ | 1575 | /* check if we need to merge IBSS */ |
2828 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && | 1576 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && |
2829 | !local->sta_sw_scanning && !local->sta_hw_scanning && | ||
2830 | bss->capability & WLAN_CAPABILITY_IBSS && | 1577 | bss->capability & WLAN_CAPABILITY_IBSS && |
2831 | bss->freq == local->oper_channel->center_freq && | 1578 | bss->freq == local->oper_channel->center_freq && |
2832 | elems->ssid_len == sdata->u.sta.ssid_len && | 1579 | elems->ssid_len == sdata->u.sta.ssid_len && |
@@ -2848,7 +1595,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2848 | * e.g: at 1 MBit that means mactime is 192 usec earlier | 1595 | * e.g: at 1 MBit that means mactime is 192 usec earlier |
2849 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | 1596 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. |
2850 | */ | 1597 | */ |
2851 | int rate = local->hw.wiphy->bands[rx_status->band]-> | 1598 | int rate = local->hw.wiphy->bands[band]-> |
2852 | bitrates[rx_status->rate_idx].bitrate; | 1599 | bitrates[rx_status->rate_idx].bitrate; |
2853 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | 1600 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); |
2854 | } else if (local && local->ops && local->ops->get_tsf) | 1601 | } else if (local && local->ops && local->ops->get_tsf) |
@@ -2871,12 +1618,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2871 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1618 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2872 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 1619 | printk(KERN_DEBUG "%s: beacon TSF higher than " |
2873 | "local TSF - IBSS merge with BSSID %s\n", | 1620 | "local TSF - IBSS merge with BSSID %s\n", |
2874 | dev->name, print_mac(mac, mgmt->bssid)); | 1621 | sdata->dev->name, print_mac(mac, mgmt->bssid)); |
2875 | #endif | 1622 | #endif |
2876 | ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); | 1623 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); |
2877 | ieee80211_ibss_add_sta(dev, NULL, | 1624 | ieee80211_ibss_add_sta(sdata, NULL, |
2878 | mgmt->bssid, mgmt->sa, | 1625 | mgmt->bssid, mgmt->sa, |
2879 | BIT(rx_status->rate_idx)); | 1626 | supp_rates); |
2880 | } | 1627 | } |
2881 | } | 1628 | } |
2882 | 1629 | ||
@@ -2884,13 +1631,17 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2884 | } | 1631 | } |
2885 | 1632 | ||
2886 | 1633 | ||
2887 | static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, | 1634 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, |
2888 | struct ieee80211_mgmt *mgmt, | 1635 | struct ieee80211_mgmt *mgmt, |
2889 | size_t len, | 1636 | size_t len, |
2890 | struct ieee80211_rx_status *rx_status) | 1637 | struct ieee80211_rx_status *rx_status) |
2891 | { | 1638 | { |
2892 | size_t baselen; | 1639 | size_t baselen; |
2893 | struct ieee802_11_elems elems; | 1640 | struct ieee802_11_elems elems; |
1641 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1642 | |||
1643 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | ||
1644 | return; /* ignore ProbeResp to foreign address */ | ||
2894 | 1645 | ||
2895 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 1646 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
2896 | if (baselen > len) | 1647 | if (baselen > len) |
@@ -2899,20 +1650,27 @@ static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, | |||
2899 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 1650 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
2900 | &elems); | 1651 | &elems); |
2901 | 1652 | ||
2902 | ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0); | 1653 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
1654 | |||
1655 | /* direct probe may be part of the association flow */ | ||
1656 | if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, | ||
1657 | &ifsta->request)) { | ||
1658 | printk(KERN_DEBUG "%s direct probe responded\n", | ||
1659 | sdata->dev->name); | ||
1660 | ieee80211_authenticate(sdata, ifsta); | ||
1661 | } | ||
2903 | } | 1662 | } |
2904 | 1663 | ||
2905 | 1664 | ||
2906 | static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | 1665 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, |
2907 | struct ieee80211_mgmt *mgmt, | 1666 | struct ieee80211_mgmt *mgmt, |
2908 | size_t len, | 1667 | size_t len, |
2909 | struct ieee80211_rx_status *rx_status) | 1668 | struct ieee80211_rx_status *rx_status) |
2910 | { | 1669 | { |
2911 | struct ieee80211_sub_if_data *sdata; | ||
2912 | struct ieee80211_if_sta *ifsta; | 1670 | struct ieee80211_if_sta *ifsta; |
2913 | size_t baselen; | 1671 | size_t baselen; |
2914 | struct ieee802_11_elems elems; | 1672 | struct ieee802_11_elems elems; |
2915 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1673 | struct ieee80211_local *local = sdata->local; |
2916 | struct ieee80211_conf *conf = &local->hw.conf; | 1674 | struct ieee80211_conf *conf = &local->hw.conf; |
2917 | u32 changed = 0; | 1675 | u32 changed = 0; |
2918 | 1676 | ||
@@ -2923,10 +1681,9 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2923 | 1681 | ||
2924 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | 1682 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
2925 | 1683 | ||
2926 | ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1); | 1684 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); |
2927 | 1685 | ||
2928 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1686 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2929 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
2930 | return; | 1687 | return; |
2931 | ifsta = &sdata->u.sta; | 1688 | ifsta = &sdata->u.sta; |
2932 | 1689 | ||
@@ -2934,15 +1691,9 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2934 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) | 1691 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) |
2935 | return; | 1692 | return; |
2936 | 1693 | ||
2937 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 1694 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
2938 | elems.wmm_param_len); | 1695 | elems.wmm_param_len); |
2939 | 1696 | ||
2940 | /* Do not send changes to driver if we are scanning. This removes | ||
2941 | * requirement that driver's bss_info_changed function needs to be | ||
2942 | * atomic. */ | ||
2943 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
2944 | return; | ||
2945 | |||
2946 | if (elems.erp_info && elems.erp_info_len >= 1) | 1697 | if (elems.erp_info && elems.erp_info_len >= 1) |
2947 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); | 1698 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); |
2948 | else { | 1699 | else { |
@@ -2956,7 +1707,6 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2956 | struct ieee80211_ht_bss_info bss_info; | 1707 | struct ieee80211_ht_bss_info bss_info; |
2957 | 1708 | ||
2958 | ieee80211_ht_addt_info_ie_to_ht_bss_info( | 1709 | ieee80211_ht_addt_info_ie_to_ht_bss_info( |
2959 | (struct ieee80211_ht_addt_info *) | ||
2960 | elems.ht_info_elem, &bss_info); | 1710 | elems.ht_info_elem, &bss_info); |
2961 | changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, | 1711 | changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, |
2962 | &bss_info); | 1712 | &bss_info); |
@@ -2966,14 +1716,13 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2966 | } | 1716 | } |
2967 | 1717 | ||
2968 | 1718 | ||
2969 | static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | 1719 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, |
2970 | struct ieee80211_if_sta *ifsta, | 1720 | struct ieee80211_if_sta *ifsta, |
2971 | struct ieee80211_mgmt *mgmt, | 1721 | struct ieee80211_mgmt *mgmt, |
2972 | size_t len, | 1722 | size_t len, |
2973 | struct ieee80211_rx_status *rx_status) | 1723 | struct ieee80211_rx_status *rx_status) |
2974 | { | 1724 | { |
2975 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1725 | struct ieee80211_local *local = sdata->local; |
2976 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2977 | int tx_last_beacon; | 1726 | int tx_last_beacon; |
2978 | struct sk_buff *skb; | 1727 | struct sk_buff *skb; |
2979 | struct ieee80211_mgmt *resp; | 1728 | struct ieee80211_mgmt *resp; |
@@ -2984,8 +1733,8 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
2984 | DECLARE_MAC_BUF(mac3); | 1733 | DECLARE_MAC_BUF(mac3); |
2985 | #endif | 1734 | #endif |
2986 | 1735 | ||
2987 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS || | 1736 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC || |
2988 | ifsta->state != IEEE80211_IBSS_JOINED || | 1737 | ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || |
2989 | len < 24 + 2 || !ifsta->probe_resp) | 1738 | len < 24 + 2 || !ifsta->probe_resp) |
2990 | return; | 1739 | return; |
2991 | 1740 | ||
@@ -2997,7 +1746,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
2997 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1746 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2998 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" | 1747 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" |
2999 | "%s (tx_last_beacon=%d)\n", | 1748 | "%s (tx_last_beacon=%d)\n", |
3000 | dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), | 1749 | sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), |
3001 | print_mac(mac3, mgmt->bssid), tx_last_beacon); | 1750 | print_mac(mac3, mgmt->bssid), tx_last_beacon); |
3002 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1751 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3003 | 1752 | ||
@@ -3015,7 +1764,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
3015 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1764 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3016 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 1765 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " |
3017 | "from %s\n", | 1766 | "from %s\n", |
3018 | dev->name, print_mac(mac, mgmt->sa)); | 1767 | sdata->dev->name, print_mac(mac, mgmt->sa)); |
3019 | #endif | 1768 | #endif |
3020 | return; | 1769 | return; |
3021 | } | 1770 | } |
@@ -3035,74 +1784,15 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
3035 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 1784 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
3036 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1785 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3037 | printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", | 1786 | printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", |
3038 | dev->name, print_mac(mac, resp->da)); | 1787 | sdata->dev->name, print_mac(mac, resp->da)); |
3039 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1788 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3040 | ieee80211_sta_tx(dev, skb, 0); | 1789 | ieee80211_tx_skb(sdata, skb, 0); |
3041 | } | 1790 | } |
3042 | 1791 | ||
3043 | static void ieee80211_rx_mgmt_action(struct net_device *dev, | 1792 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
3044 | struct ieee80211_if_sta *ifsta, | ||
3045 | struct ieee80211_mgmt *mgmt, | ||
3046 | size_t len, | ||
3047 | struct ieee80211_rx_status *rx_status) | ||
3048 | { | ||
3049 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3050 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3051 | |||
3052 | if (len < IEEE80211_MIN_ACTION_SIZE) | ||
3053 | return; | ||
3054 | |||
3055 | switch (mgmt->u.action.category) { | ||
3056 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
3057 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | ||
3058 | break; | ||
3059 | switch (mgmt->u.action.u.chan_switch.action_code) { | ||
3060 | case WLAN_ACTION_SPCT_MSR_REQ: | ||
3061 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3062 | sizeof(mgmt->u.action.u.measurement))) | ||
3063 | break; | ||
3064 | ieee80211_sta_process_measurement_req(dev, mgmt, len); | ||
3065 | break; | ||
3066 | } | ||
3067 | break; | ||
3068 | case WLAN_CATEGORY_BACK: | ||
3069 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
3070 | case WLAN_ACTION_ADDBA_REQ: | ||
3071 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3072 | sizeof(mgmt->u.action.u.addba_req))) | ||
3073 | break; | ||
3074 | ieee80211_sta_process_addba_request(dev, mgmt, len); | ||
3075 | break; | ||
3076 | case WLAN_ACTION_ADDBA_RESP: | ||
3077 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3078 | sizeof(mgmt->u.action.u.addba_resp))) | ||
3079 | break; | ||
3080 | ieee80211_sta_process_addba_resp(dev, mgmt, len); | ||
3081 | break; | ||
3082 | case WLAN_ACTION_DELBA: | ||
3083 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3084 | sizeof(mgmt->u.action.u.delba))) | ||
3085 | break; | ||
3086 | ieee80211_sta_process_delba(dev, mgmt, len); | ||
3087 | break; | ||
3088 | } | ||
3089 | break; | ||
3090 | case PLINK_CATEGORY: | ||
3091 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
3092 | mesh_rx_plink_frame(dev, mgmt, len, rx_status); | ||
3093 | break; | ||
3094 | case MESH_PATH_SEL_CATEGORY: | ||
3095 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
3096 | mesh_rx_path_sel_frame(dev, mgmt, len); | ||
3097 | break; | ||
3098 | } | ||
3099 | } | ||
3100 | |||
3101 | void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | ||
3102 | struct ieee80211_rx_status *rx_status) | 1793 | struct ieee80211_rx_status *rx_status) |
3103 | { | 1794 | { |
3104 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1795 | struct ieee80211_local *local = sdata->local; |
3105 | struct ieee80211_sub_if_data *sdata; | ||
3106 | struct ieee80211_if_sta *ifsta; | 1796 | struct ieee80211_if_sta *ifsta; |
3107 | struct ieee80211_mgmt *mgmt; | 1797 | struct ieee80211_mgmt *mgmt; |
3108 | u16 fc; | 1798 | u16 fc; |
@@ -3110,7 +1800,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | |||
3110 | if (skb->len < 24) | 1800 | if (skb->len < 24) |
3111 | goto fail; | 1801 | goto fail; |
3112 | 1802 | ||
3113 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3114 | ifsta = &sdata->u.sta; | 1803 | ifsta = &sdata->u.sta; |
3115 | 1804 | ||
3116 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1805 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -3120,7 +1809,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | |||
3120 | case IEEE80211_STYPE_PROBE_REQ: | 1809 | case IEEE80211_STYPE_PROBE_REQ: |
3121 | case IEEE80211_STYPE_PROBE_RESP: | 1810 | case IEEE80211_STYPE_PROBE_RESP: |
3122 | case IEEE80211_STYPE_BEACON: | 1811 | case IEEE80211_STYPE_BEACON: |
3123 | case IEEE80211_STYPE_ACTION: | ||
3124 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); | 1812 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); |
3125 | case IEEE80211_STYPE_AUTH: | 1813 | case IEEE80211_STYPE_AUTH: |
3126 | case IEEE80211_STYPE_ASSOC_RESP: | 1814 | case IEEE80211_STYPE_ASSOC_RESP: |
@@ -3136,17 +1824,14 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | |||
3136 | kfree_skb(skb); | 1824 | kfree_skb(skb); |
3137 | } | 1825 | } |
3138 | 1826 | ||
3139 | 1827 | static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |
3140 | static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | ||
3141 | struct sk_buff *skb) | 1828 | struct sk_buff *skb) |
3142 | { | 1829 | { |
3143 | struct ieee80211_rx_status *rx_status; | 1830 | struct ieee80211_rx_status *rx_status; |
3144 | struct ieee80211_sub_if_data *sdata; | ||
3145 | struct ieee80211_if_sta *ifsta; | 1831 | struct ieee80211_if_sta *ifsta; |
3146 | struct ieee80211_mgmt *mgmt; | 1832 | struct ieee80211_mgmt *mgmt; |
3147 | u16 fc; | 1833 | u16 fc; |
3148 | 1834 | ||
3149 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3150 | ifsta = &sdata->u.sta; | 1835 | ifsta = &sdata->u.sta; |
3151 | 1836 | ||
3152 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 1837 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
@@ -3155,17 +1840,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | |||
3155 | 1840 | ||
3156 | switch (fc & IEEE80211_FCTL_STYPE) { | 1841 | switch (fc & IEEE80211_FCTL_STYPE) { |
3157 | case IEEE80211_STYPE_PROBE_REQ: | 1842 | case IEEE80211_STYPE_PROBE_REQ: |
3158 | ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len, | 1843 | ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, |
3159 | rx_status); | 1844 | rx_status); |
3160 | break; | 1845 | break; |
3161 | case IEEE80211_STYPE_PROBE_RESP: | 1846 | case IEEE80211_STYPE_PROBE_RESP: |
3162 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); | 1847 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); |
3163 | break; | 1848 | break; |
3164 | case IEEE80211_STYPE_BEACON: | 1849 | case IEEE80211_STYPE_BEACON: |
3165 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); | 1850 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); |
3166 | break; | 1851 | break; |
3167 | case IEEE80211_STYPE_AUTH: | 1852 | case IEEE80211_STYPE_AUTH: |
3168 | ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len); | 1853 | ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); |
3169 | break; | 1854 | break; |
3170 | case IEEE80211_STYPE_ASSOC_RESP: | 1855 | case IEEE80211_STYPE_ASSOC_RESP: |
3171 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); | 1856 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); |
@@ -3174,13 +1859,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | |||
3174 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); | 1859 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); |
3175 | break; | 1860 | break; |
3176 | case IEEE80211_STYPE_DEAUTH: | 1861 | case IEEE80211_STYPE_DEAUTH: |
3177 | ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len); | 1862 | ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); |
3178 | break; | 1863 | break; |
3179 | case IEEE80211_STYPE_DISASSOC: | 1864 | case IEEE80211_STYPE_DISASSOC: |
3180 | ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); | 1865 | ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); |
3181 | break; | ||
3182 | case IEEE80211_STYPE_ACTION: | ||
3183 | ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status); | ||
3184 | break; | 1866 | break; |
3185 | } | 1867 | } |
3186 | 1868 | ||
@@ -3188,47 +1870,11 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | |||
3188 | } | 1870 | } |
3189 | 1871 | ||
3190 | 1872 | ||
3191 | ieee80211_rx_result | 1873 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) |
3192 | ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, | ||
3193 | struct ieee80211_rx_status *rx_status) | ||
3194 | { | 1874 | { |
3195 | struct ieee80211_mgmt *mgmt; | 1875 | struct ieee80211_local *local = sdata->local; |
3196 | __le16 fc; | ||
3197 | |||
3198 | if (skb->len < 2) | ||
3199 | return RX_DROP_UNUSABLE; | ||
3200 | |||
3201 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
3202 | fc = mgmt->frame_control; | ||
3203 | |||
3204 | if (ieee80211_is_ctl(fc)) | ||
3205 | return RX_CONTINUE; | ||
3206 | |||
3207 | if (skb->len < 24) | ||
3208 | return RX_DROP_MONITOR; | ||
3209 | |||
3210 | if (ieee80211_is_probe_resp(fc)) { | ||
3211 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); | ||
3212 | dev_kfree_skb(skb); | ||
3213 | return RX_QUEUED; | ||
3214 | } | ||
3215 | |||
3216 | if (ieee80211_is_beacon(fc)) { | ||
3217 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); | ||
3218 | dev_kfree_skb(skb); | ||
3219 | return RX_QUEUED; | ||
3220 | } | ||
3221 | |||
3222 | return RX_CONTINUE; | ||
3223 | } | ||
3224 | |||
3225 | |||
3226 | static int ieee80211_sta_active_ibss(struct net_device *dev) | ||
3227 | { | ||
3228 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3229 | int active = 0; | 1876 | int active = 0; |
3230 | struct sta_info *sta; | 1877 | struct sta_info *sta; |
3231 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3232 | 1878 | ||
3233 | rcu_read_lock(); | 1879 | rcu_read_lock(); |
3234 | 1880 | ||
@@ -3247,179 +1893,36 @@ static int ieee80211_sta_active_ibss(struct net_device *dev) | |||
3247 | } | 1893 | } |
3248 | 1894 | ||
3249 | 1895 | ||
3250 | static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) | 1896 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, |
3251 | { | ||
3252 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3253 | struct sta_info *sta, *tmp; | ||
3254 | LIST_HEAD(tmp_list); | ||
3255 | DECLARE_MAC_BUF(mac); | ||
3256 | unsigned long flags; | ||
3257 | |||
3258 | spin_lock_irqsave(&local->sta_lock, flags); | ||
3259 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | ||
3260 | if (time_after(jiffies, sta->last_rx + exp_time)) { | ||
3261 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
3262 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | ||
3263 | dev->name, print_mac(mac, sta->addr)); | ||
3264 | #endif | ||
3265 | __sta_info_unlink(&sta); | ||
3266 | if (sta) | ||
3267 | list_add(&sta->list, &tmp_list); | ||
3268 | } | ||
3269 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
3270 | |||
3271 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
3272 | sta_info_destroy(sta); | ||
3273 | } | ||
3274 | |||
3275 | |||
3276 | static void ieee80211_sta_merge_ibss(struct net_device *dev, | ||
3277 | struct ieee80211_if_sta *ifsta) | 1897 | struct ieee80211_if_sta *ifsta) |
3278 | { | 1898 | { |
3279 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1899 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
3280 | 1900 | ||
3281 | ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT); | 1901 | ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); |
3282 | if (ieee80211_sta_active_ibss(dev)) | 1902 | if (ieee80211_sta_active_ibss(sdata)) |
3283 | return; | 1903 | return; |
3284 | 1904 | ||
3285 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 1905 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
3286 | "IBSS networks with same SSID (merge)\n", dev->name); | 1906 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); |
3287 | ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len); | 1907 | ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); |
3288 | } | 1908 | } |
3289 | 1909 | ||
3290 | 1910 | ||
3291 | #ifdef CONFIG_MAC80211_MESH | 1911 | static void ieee80211_sta_timer(unsigned long data) |
3292 | static void ieee80211_mesh_housekeeping(struct net_device *dev, | ||
3293 | struct ieee80211_if_sta *ifsta) | ||
3294 | { | ||
3295 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3296 | bool free_plinks; | ||
3297 | |||
3298 | ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | ||
3299 | mesh_path_expire(dev); | ||
3300 | |||
3301 | free_plinks = mesh_plink_availables(sdata); | ||
3302 | if (free_plinks != sdata->u.sta.accepting_plinks) | ||
3303 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
3304 | |||
3305 | mod_timer(&ifsta->timer, jiffies + | ||
3306 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); | ||
3307 | } | ||
3308 | |||
3309 | |||
3310 | void ieee80211_start_mesh(struct net_device *dev) | ||
3311 | { | ||
3312 | struct ieee80211_if_sta *ifsta; | ||
3313 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3314 | ifsta = &sdata->u.sta; | ||
3315 | ifsta->state = IEEE80211_MESH_UP; | ||
3316 | ieee80211_sta_timer((unsigned long)sdata); | ||
3317 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
3318 | } | ||
3319 | #endif | ||
3320 | |||
3321 | |||
3322 | void ieee80211_sta_timer(unsigned long data) | ||
3323 | { | 1912 | { |
3324 | struct ieee80211_sub_if_data *sdata = | 1913 | struct ieee80211_sub_if_data *sdata = |
3325 | (struct ieee80211_sub_if_data *) data; | 1914 | (struct ieee80211_sub_if_data *) data; |
3326 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 1915 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
3327 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 1916 | struct ieee80211_local *local = sdata->local; |
3328 | 1917 | ||
3329 | set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); | 1918 | set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); |
3330 | queue_work(local->hw.workqueue, &ifsta->work); | 1919 | queue_work(local->hw.workqueue, &ifsta->work); |
3331 | } | 1920 | } |
3332 | 1921 | ||
3333 | void ieee80211_sta_work(struct work_struct *work) | 1922 | static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, |
3334 | { | ||
3335 | struct ieee80211_sub_if_data *sdata = | ||
3336 | container_of(work, struct ieee80211_sub_if_data, u.sta.work); | ||
3337 | struct net_device *dev = sdata->dev; | ||
3338 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3339 | struct ieee80211_if_sta *ifsta; | ||
3340 | struct sk_buff *skb; | ||
3341 | |||
3342 | if (!netif_running(dev)) | ||
3343 | return; | ||
3344 | |||
3345 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
3346 | return; | ||
3347 | |||
3348 | if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && | ||
3349 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | ||
3350 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) | ||
3351 | return; | ||
3352 | ifsta = &sdata->u.sta; | ||
3353 | |||
3354 | while ((skb = skb_dequeue(&ifsta->skb_queue))) | ||
3355 | ieee80211_sta_rx_queued_mgmt(dev, skb); | ||
3356 | |||
3357 | #ifdef CONFIG_MAC80211_MESH | ||
3358 | if (ifsta->preq_queue_len && | ||
3359 | time_after(jiffies, | ||
3360 | ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) | ||
3361 | mesh_path_start_discovery(dev); | ||
3362 | #endif | ||
3363 | |||
3364 | if (ifsta->state != IEEE80211_AUTHENTICATE && | ||
3365 | ifsta->state != IEEE80211_ASSOCIATE && | ||
3366 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { | ||
3367 | if (ifsta->scan_ssid_len) | ||
3368 | ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len); | ||
3369 | else | ||
3370 | ieee80211_sta_start_scan(dev, NULL, 0); | ||
3371 | return; | ||
3372 | } | ||
3373 | |||
3374 | if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { | ||
3375 | if (ieee80211_sta_config_auth(dev, ifsta)) | ||
3376 | return; | ||
3377 | clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); | ||
3378 | } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) | ||
3379 | return; | ||
3380 | |||
3381 | switch (ifsta->state) { | ||
3382 | case IEEE80211_DISABLED: | ||
3383 | break; | ||
3384 | case IEEE80211_AUTHENTICATE: | ||
3385 | ieee80211_authenticate(dev, ifsta); | ||
3386 | break; | ||
3387 | case IEEE80211_ASSOCIATE: | ||
3388 | ieee80211_associate(dev, ifsta); | ||
3389 | break; | ||
3390 | case IEEE80211_ASSOCIATED: | ||
3391 | ieee80211_associated(dev, ifsta); | ||
3392 | break; | ||
3393 | case IEEE80211_IBSS_SEARCH: | ||
3394 | ieee80211_sta_find_ibss(dev, ifsta); | ||
3395 | break; | ||
3396 | case IEEE80211_IBSS_JOINED: | ||
3397 | ieee80211_sta_merge_ibss(dev, ifsta); | ||
3398 | break; | ||
3399 | #ifdef CONFIG_MAC80211_MESH | ||
3400 | case IEEE80211_MESH_UP: | ||
3401 | ieee80211_mesh_housekeeping(dev, ifsta); | ||
3402 | break; | ||
3403 | #endif | ||
3404 | default: | ||
3405 | WARN_ON(1); | ||
3406 | break; | ||
3407 | } | ||
3408 | |||
3409 | if (ieee80211_privacy_mismatch(dev, ifsta)) { | ||
3410 | printk(KERN_DEBUG "%s: privacy configuration mismatch and " | ||
3411 | "mixed-cell disabled - disassociate\n", dev->name); | ||
3412 | |||
3413 | ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED); | ||
3414 | ieee80211_set_disassoc(dev, ifsta, 0); | ||
3415 | } | ||
3416 | } | ||
3417 | |||
3418 | |||
3419 | static void ieee80211_sta_reset_auth(struct net_device *dev, | ||
3420 | struct ieee80211_if_sta *ifsta) | 1923 | struct ieee80211_if_sta *ifsta) |
3421 | { | 1924 | { |
3422 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1925 | struct ieee80211_local *local = sdata->local; |
3423 | 1926 | ||
3424 | if (local->ops->reset_tsf) { | 1927 | if (local->ops->reset_tsf) { |
3425 | /* Reset own TSF to allow time synchronization work. */ | 1928 | /* Reset own TSF to allow time synchronization work. */ |
@@ -3439,29 +1942,15 @@ static void ieee80211_sta_reset_auth(struct net_device *dev, | |||
3439 | ifsta->auth_alg = WLAN_AUTH_OPEN; | 1942 | ifsta->auth_alg = WLAN_AUTH_OPEN; |
3440 | ifsta->auth_transaction = -1; | 1943 | ifsta->auth_transaction = -1; |
3441 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | 1944 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
3442 | ifsta->auth_tries = ifsta->assoc_tries = 0; | 1945 | ifsta->assoc_scan_tries = 0; |
3443 | netif_carrier_off(dev); | 1946 | ifsta->direct_probe_tries = 0; |
1947 | ifsta->auth_tries = 0; | ||
1948 | ifsta->assoc_tries = 0; | ||
1949 | netif_tx_stop_all_queues(sdata->dev); | ||
1950 | netif_carrier_off(sdata->dev); | ||
3444 | } | 1951 | } |
3445 | 1952 | ||
3446 | 1953 | ||
3447 | void ieee80211_sta_req_auth(struct net_device *dev, | ||
3448 | struct ieee80211_if_sta *ifsta) | ||
3449 | { | ||
3450 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3451 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3452 | |||
3453 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
3454 | return; | ||
3455 | |||
3456 | if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | | ||
3457 | IEEE80211_STA_AUTO_BSSID_SEL)) && | ||
3458 | (ifsta->flags & (IEEE80211_STA_SSID_SET | | ||
3459 | IEEE80211_STA_AUTO_SSID_SEL))) { | ||
3460 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | ||
3461 | queue_work(local->hw.workqueue, &ifsta->work); | ||
3462 | } | ||
3463 | } | ||
3464 | |||
3465 | static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, | 1954 | static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, |
3466 | const char *ssid, int ssid_len) | 1955 | const char *ssid, int ssid_len) |
3467 | { | 1956 | { |
@@ -3492,81 +1981,11 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, | |||
3492 | return 0; | 1981 | return 0; |
3493 | } | 1982 | } |
3494 | 1983 | ||
3495 | static int ieee80211_sta_config_auth(struct net_device *dev, | 1984 | static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, |
3496 | struct ieee80211_if_sta *ifsta) | ||
3497 | { | ||
3498 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3499 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3500 | struct ieee80211_sta_bss *bss, *selected = NULL; | ||
3501 | int top_rssi = 0, freq; | ||
3502 | |||
3503 | spin_lock_bh(&local->sta_bss_lock); | ||
3504 | freq = local->oper_channel->center_freq; | ||
3505 | list_for_each_entry(bss, &local->sta_bss_list, list) { | ||
3506 | if (!(bss->capability & WLAN_CAPABILITY_ESS)) | ||
3507 | continue; | ||
3508 | |||
3509 | if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | | ||
3510 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
3511 | IEEE80211_STA_AUTO_CHANNEL_SEL)) && | ||
3512 | (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ | ||
3513 | !!sdata->default_key)) | ||
3514 | continue; | ||
3515 | |||
3516 | if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && | ||
3517 | bss->freq != freq) | ||
3518 | continue; | ||
3519 | |||
3520 | if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && | ||
3521 | memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) | ||
3522 | continue; | ||
3523 | |||
3524 | if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && | ||
3525 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) | ||
3526 | continue; | ||
3527 | |||
3528 | if (!selected || top_rssi < bss->signal) { | ||
3529 | selected = bss; | ||
3530 | top_rssi = bss->signal; | ||
3531 | } | ||
3532 | } | ||
3533 | if (selected) | ||
3534 | atomic_inc(&selected->users); | ||
3535 | spin_unlock_bh(&local->sta_bss_lock); | ||
3536 | |||
3537 | if (selected) { | ||
3538 | ieee80211_set_freq(dev, selected->freq); | ||
3539 | if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) | ||
3540 | ieee80211_sta_set_ssid(dev, selected->ssid, | ||
3541 | selected->ssid_len); | ||
3542 | ieee80211_sta_set_bssid(dev, selected->bssid); | ||
3543 | ieee80211_sta_def_wmm_params(dev, selected, 0); | ||
3544 | ieee80211_rx_bss_put(local, selected); | ||
3545 | ifsta->state = IEEE80211_AUTHENTICATE; | ||
3546 | ieee80211_sta_reset_auth(dev, ifsta); | ||
3547 | return 0; | ||
3548 | } else { | ||
3549 | if (ifsta->state != IEEE80211_AUTHENTICATE) { | ||
3550 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) | ||
3551 | ieee80211_sta_start_scan(dev, NULL, 0); | ||
3552 | else | ||
3553 | ieee80211_sta_start_scan(dev, ifsta->ssid, | ||
3554 | ifsta->ssid_len); | ||
3555 | ifsta->state = IEEE80211_AUTHENTICATE; | ||
3556 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | ||
3557 | } else | ||
3558 | ifsta->state = IEEE80211_DISABLED; | ||
3559 | } | ||
3560 | return -1; | ||
3561 | } | ||
3562 | |||
3563 | |||
3564 | static int ieee80211_sta_create_ibss(struct net_device *dev, | ||
3565 | struct ieee80211_if_sta *ifsta) | 1985 | struct ieee80211_if_sta *ifsta) |
3566 | { | 1986 | { |
3567 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1987 | struct ieee80211_local *local = sdata->local; |
3568 | struct ieee80211_sta_bss *bss; | 1988 | struct ieee80211_bss *bss; |
3569 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3570 | struct ieee80211_supported_band *sband; | 1989 | struct ieee80211_supported_band *sband; |
3571 | u8 bssid[ETH_ALEN], *pos; | 1990 | u8 bssid[ETH_ALEN], *pos; |
3572 | int i; | 1991 | int i; |
@@ -3582,15 +2001,15 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3582 | * random number generator get different BSSID. */ | 2001 | * random number generator get different BSSID. */ |
3583 | get_random_bytes(bssid, ETH_ALEN); | 2002 | get_random_bytes(bssid, ETH_ALEN); |
3584 | for (i = 0; i < ETH_ALEN; i++) | 2003 | for (i = 0; i < ETH_ALEN; i++) |
3585 | bssid[i] ^= dev->dev_addr[i]; | 2004 | bssid[i] ^= sdata->dev->dev_addr[i]; |
3586 | bssid[0] &= ~0x01; | 2005 | bssid[0] &= ~0x01; |
3587 | bssid[0] |= 0x02; | 2006 | bssid[0] |= 0x02; |
3588 | #endif | 2007 | #endif |
3589 | 2008 | ||
3590 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", | 2009 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", |
3591 | dev->name, print_mac(mac, bssid)); | 2010 | sdata->dev->name, print_mac(mac, bssid)); |
3592 | 2011 | ||
3593 | bss = ieee80211_rx_bss_add(dev, bssid, | 2012 | bss = ieee80211_rx_bss_add(local, bssid, |
3594 | local->hw.conf.channel->center_freq, | 2013 | local->hw.conf.channel->center_freq, |
3595 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); | 2014 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); |
3596 | if (!bss) | 2015 | if (!bss) |
@@ -3617,17 +2036,17 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3617 | *pos++ = (u8) (rate / 5); | 2036 | *pos++ = (u8) (rate / 5); |
3618 | } | 2037 | } |
3619 | 2038 | ||
3620 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 2039 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); |
3621 | ieee80211_rx_bss_put(local, bss); | 2040 | ieee80211_rx_bss_put(local, bss); |
3622 | return ret; | 2041 | return ret; |
3623 | } | 2042 | } |
3624 | 2043 | ||
3625 | 2044 | ||
3626 | static int ieee80211_sta_find_ibss(struct net_device *dev, | 2045 | static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, |
3627 | struct ieee80211_if_sta *ifsta) | 2046 | struct ieee80211_if_sta *ifsta) |
3628 | { | 2047 | { |
3629 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2048 | struct ieee80211_local *local = sdata->local; |
3630 | struct ieee80211_sta_bss *bss; | 2049 | struct ieee80211_bss *bss; |
3631 | int found = 0; | 2050 | int found = 0; |
3632 | u8 bssid[ETH_ALEN]; | 2051 | u8 bssid[ETH_ALEN]; |
3633 | int active_ibss; | 2052 | int active_ibss; |
@@ -3637,13 +2056,13 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3637 | if (ifsta->ssid_len == 0) | 2056 | if (ifsta->ssid_len == 0) |
3638 | return -EINVAL; | 2057 | return -EINVAL; |
3639 | 2058 | ||
3640 | active_ibss = ieee80211_sta_active_ibss(dev); | 2059 | active_ibss = ieee80211_sta_active_ibss(sdata); |
3641 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2060 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3642 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 2061 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", |
3643 | dev->name, active_ibss); | 2062 | sdata->dev->name, active_ibss); |
3644 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2063 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3645 | spin_lock_bh(&local->sta_bss_lock); | 2064 | spin_lock_bh(&local->bss_lock); |
3646 | list_for_each_entry(bss, &local->sta_bss_list, list) { | 2065 | list_for_each_entry(bss, &local->bss_list, list) { |
3647 | if (ifsta->ssid_len != bss->ssid_len || | 2066 | if (ifsta->ssid_len != bss->ssid_len || |
3648 | memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 | 2067 | memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 |
3649 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) | 2068 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) |
@@ -3657,7 +2076,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3657 | if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) | 2076 | if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) |
3658 | break; | 2077 | break; |
3659 | } | 2078 | } |
3660 | spin_unlock_bh(&local->sta_bss_lock); | 2079 | spin_unlock_bh(&local->bss_lock); |
3661 | 2080 | ||
3662 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2081 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3663 | if (found) | 2082 | if (found) |
@@ -3675,15 +2094,15 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3675 | else | 2094 | else |
3676 | search_freq = local->hw.conf.channel->center_freq; | 2095 | search_freq = local->hw.conf.channel->center_freq; |
3677 | 2096 | ||
3678 | bss = ieee80211_rx_bss_get(dev, bssid, search_freq, | 2097 | bss = ieee80211_rx_bss_get(local, bssid, search_freq, |
3679 | ifsta->ssid, ifsta->ssid_len); | 2098 | ifsta->ssid, ifsta->ssid_len); |
3680 | if (!bss) | 2099 | if (!bss) |
3681 | goto dont_join; | 2100 | goto dont_join; |
3682 | 2101 | ||
3683 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" | 2102 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" |
3684 | " based on configured SSID\n", | 2103 | " based on configured SSID\n", |
3685 | dev->name, print_mac(mac, bssid)); | 2104 | sdata->dev->name, print_mac(mac, bssid)); |
3686 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 2105 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); |
3687 | ieee80211_rx_bss_put(local, bss); | 2106 | ieee80211_rx_bss_put(local, bss); |
3688 | return ret; | 2107 | return ret; |
3689 | } | 2108 | } |
@@ -3694,17 +2113,17 @@ dont_join: | |||
3694 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2113 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3695 | 2114 | ||
3696 | /* Selected IBSS not found in current scan results - try to scan */ | 2115 | /* Selected IBSS not found in current scan results - try to scan */ |
3697 | if (ifsta->state == IEEE80211_IBSS_JOINED && | 2116 | if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED && |
3698 | !ieee80211_sta_active_ibss(dev)) { | 2117 | !ieee80211_sta_active_ibss(sdata)) { |
3699 | mod_timer(&ifsta->timer, jiffies + | 2118 | mod_timer(&ifsta->timer, jiffies + |
3700 | IEEE80211_IBSS_MERGE_INTERVAL); | 2119 | IEEE80211_IBSS_MERGE_INTERVAL); |
3701 | } else if (time_after(jiffies, local->last_scan_completed + | 2120 | } else if (time_after(jiffies, local->last_scan_completed + |
3702 | IEEE80211_SCAN_INTERVAL)) { | 2121 | IEEE80211_SCAN_INTERVAL)) { |
3703 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 2122 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
3704 | "join\n", dev->name); | 2123 | "join\n", sdata->dev->name); |
3705 | return ieee80211_sta_req_scan(dev, ifsta->ssid, | 2124 | return ieee80211_request_scan(sdata, ifsta->ssid, |
3706 | ifsta->ssid_len); | 2125 | ifsta->ssid_len); |
3707 | } else if (ifsta->state != IEEE80211_IBSS_JOINED) { | 2126 | } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { |
3708 | int interval = IEEE80211_SCAN_INTERVAL; | 2127 | int interval = IEEE80211_SCAN_INTERVAL; |
3709 | 2128 | ||
3710 | if (time_after(jiffies, ifsta->ibss_join_req + | 2129 | if (time_after(jiffies, ifsta->ibss_join_req + |
@@ -3712,10 +2131,10 @@ dont_join: | |||
3712 | if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && | 2131 | if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && |
3713 | (!(local->oper_channel->flags & | 2132 | (!(local->oper_channel->flags & |
3714 | IEEE80211_CHAN_NO_IBSS))) | 2133 | IEEE80211_CHAN_NO_IBSS))) |
3715 | return ieee80211_sta_create_ibss(dev, ifsta); | 2134 | return ieee80211_sta_create_ibss(sdata, ifsta); |
3716 | if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { | 2135 | if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { |
3717 | printk(KERN_DEBUG "%s: IBSS not allowed on" | 2136 | printk(KERN_DEBUG "%s: IBSS not allowed on" |
3718 | " %d MHz\n", dev->name, | 2137 | " %d MHz\n", sdata->dev->name, |
3719 | local->hw.conf.channel->center_freq); | 2138 | local->hw.conf.channel->center_freq); |
3720 | } | 2139 | } |
3721 | 2140 | ||
@@ -3724,7 +2143,7 @@ dont_join: | |||
3724 | interval = IEEE80211_SCAN_INTERVAL_SLOW; | 2143 | interval = IEEE80211_SCAN_INTERVAL_SLOW; |
3725 | } | 2144 | } |
3726 | 2145 | ||
3727 | ifsta->state = IEEE80211_IBSS_SEARCH; | 2146 | ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; |
3728 | mod_timer(&ifsta->timer, jiffies + interval); | 2147 | mod_timer(&ifsta->timer, jiffies + interval); |
3729 | return 0; | 2148 | return 0; |
3730 | } | 2149 | } |
@@ -3733,620 +2152,344 @@ dont_join: | |||
3733 | } | 2152 | } |
3734 | 2153 | ||
3735 | 2154 | ||
3736 | int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) | 2155 | static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, |
2156 | struct ieee80211_if_sta *ifsta) | ||
3737 | { | 2157 | { |
3738 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2158 | struct ieee80211_local *local = sdata->local; |
3739 | struct ieee80211_if_sta *ifsta; | 2159 | struct ieee80211_bss *bss, *selected = NULL; |
3740 | int res; | 2160 | int top_rssi = 0, freq; |
3741 | 2161 | ||
3742 | if (len > IEEE80211_MAX_SSID_LEN) | 2162 | spin_lock_bh(&local->bss_lock); |
3743 | return -EINVAL; | 2163 | freq = local->oper_channel->center_freq; |
2164 | list_for_each_entry(bss, &local->bss_list, list) { | ||
2165 | if (!(bss->capability & WLAN_CAPABILITY_ESS)) | ||
2166 | continue; | ||
3744 | 2167 | ||
3745 | ifsta = &sdata->u.sta; | 2168 | if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | |
2169 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
2170 | IEEE80211_STA_AUTO_CHANNEL_SEL)) && | ||
2171 | (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ | ||
2172 | !!sdata->default_key)) | ||
2173 | continue; | ||
3746 | 2174 | ||
3747 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { | 2175 | if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && |
3748 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); | 2176 | bss->freq != freq) |
3749 | memcpy(ifsta->ssid, ssid, len); | 2177 | continue; |
3750 | ifsta->ssid_len = len; | ||
3751 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
3752 | 2178 | ||
3753 | res = 0; | 2179 | if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && |
3754 | /* | 2180 | memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) |
3755 | * Hack! MLME code needs to be cleaned up to have different | 2181 | continue; |
3756 | * entry points for configuration and internal selection change | ||
3757 | */ | ||
3758 | if (netif_running(sdata->dev)) | ||
3759 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
3760 | if (res) { | ||
3761 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
3762 | "the low-level driver\n", dev->name); | ||
3763 | return res; | ||
3764 | } | ||
3765 | } | ||
3766 | 2182 | ||
3767 | if (len) | 2183 | if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && |
3768 | ifsta->flags |= IEEE80211_STA_SSID_SET; | 2184 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) |
3769 | else | 2185 | continue; |
3770 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | ||
3771 | 2186 | ||
3772 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | 2187 | if (!selected || top_rssi < bss->signal) { |
3773 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { | 2188 | selected = bss; |
3774 | ifsta->ibss_join_req = jiffies; | 2189 | top_rssi = bss->signal; |
3775 | ifsta->state = IEEE80211_IBSS_SEARCH; | 2190 | } |
3776 | return ieee80211_sta_find_ibss(dev, ifsta); | ||
3777 | } | 2191 | } |
2192 | if (selected) | ||
2193 | atomic_inc(&selected->users); | ||
2194 | spin_unlock_bh(&local->bss_lock); | ||
3778 | 2195 | ||
3779 | return 0; | 2196 | if (selected) { |
3780 | } | 2197 | ieee80211_set_freq(sdata, selected->freq); |
2198 | if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) | ||
2199 | ieee80211_sta_set_ssid(sdata, selected->ssid, | ||
2200 | selected->ssid_len); | ||
2201 | ieee80211_sta_set_bssid(sdata, selected->bssid); | ||
2202 | ieee80211_sta_def_wmm_params(sdata, selected); | ||
3781 | 2203 | ||
2204 | /* Send out direct probe if no probe resp was received or | ||
2205 | * the one we have is outdated | ||
2206 | */ | ||
2207 | if (!selected->last_probe_resp || | ||
2208 | time_after(jiffies, selected->last_probe_resp | ||
2209 | + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
2210 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; | ||
2211 | else | ||
2212 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | ||
3782 | 2213 | ||
3783 | int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) | 2214 | ieee80211_rx_bss_put(local, selected); |
3784 | { | 2215 | ieee80211_sta_reset_auth(sdata, ifsta); |
3785 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2216 | return 0; |
3786 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2217 | } else { |
3787 | memcpy(ssid, ifsta->ssid, ifsta->ssid_len); | 2218 | if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { |
3788 | *len = ifsta->ssid_len; | 2219 | ifsta->assoc_scan_tries++; |
3789 | return 0; | 2220 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) |
2221 | ieee80211_start_scan(sdata, NULL, 0); | ||
2222 | else | ||
2223 | ieee80211_start_scan(sdata, ifsta->ssid, | ||
2224 | ifsta->ssid_len); | ||
2225 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | ||
2226 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | ||
2227 | } else | ||
2228 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
2229 | } | ||
2230 | return -1; | ||
3790 | } | 2231 | } |
3791 | 2232 | ||
3792 | 2233 | ||
3793 | int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) | 2234 | static void ieee80211_sta_work(struct work_struct *work) |
3794 | { | 2235 | { |
3795 | struct ieee80211_sub_if_data *sdata; | 2236 | struct ieee80211_sub_if_data *sdata = |
2237 | container_of(work, struct ieee80211_sub_if_data, u.sta.work); | ||
2238 | struct ieee80211_local *local = sdata->local; | ||
3796 | struct ieee80211_if_sta *ifsta; | 2239 | struct ieee80211_if_sta *ifsta; |
3797 | int res; | 2240 | struct sk_buff *skb; |
3798 | |||
3799 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3800 | ifsta = &sdata->u.sta; | ||
3801 | 2241 | ||
3802 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 2242 | if (!netif_running(sdata->dev)) |
3803 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | 2243 | return; |
3804 | res = 0; | ||
3805 | /* | ||
3806 | * Hack! See also ieee80211_sta_set_ssid. | ||
3807 | */ | ||
3808 | if (netif_running(sdata->dev)) | ||
3809 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | ||
3810 | if (res) { | ||
3811 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | ||
3812 | "the low-level driver\n", dev->name); | ||
3813 | return res; | ||
3814 | } | ||
3815 | } | ||
3816 | 2244 | ||
3817 | if (is_valid_ether_addr(bssid)) | 2245 | if (local->sw_scanning || local->hw_scanning) |
3818 | ifsta->flags |= IEEE80211_STA_BSSID_SET; | 2246 | return; |
3819 | else | ||
3820 | ifsta->flags &= ~IEEE80211_STA_BSSID_SET; | ||
3821 | 2247 | ||
3822 | return 0; | 2248 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION && |
3823 | } | 2249 | sdata->vif.type != NL80211_IFTYPE_ADHOC)) |
2250 | return; | ||
2251 | ifsta = &sdata->u.sta; | ||
3824 | 2252 | ||
2253 | while ((skb = skb_dequeue(&ifsta->skb_queue))) | ||
2254 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | ||
3825 | 2255 | ||
3826 | static void ieee80211_send_nullfunc(struct ieee80211_local *local, | 2256 | if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && |
3827 | struct ieee80211_sub_if_data *sdata, | 2257 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
3828 | int powersave) | 2258 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && |
3829 | { | 2259 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { |
3830 | struct sk_buff *skb; | 2260 | ieee80211_start_scan(sdata, ifsta->scan_ssid, |
3831 | struct ieee80211_hdr *nullfunc; | 2261 | ifsta->scan_ssid_len); |
3832 | __le16 fc; | 2262 | return; |
2263 | } | ||
3833 | 2264 | ||
3834 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 2265 | if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { |
3835 | if (!skb) { | 2266 | if (ieee80211_sta_config_auth(sdata, ifsta)) |
3836 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | 2267 | return; |
3837 | "frame\n", sdata->dev->name); | 2268 | clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); |
2269 | } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) | ||
3838 | return; | 2270 | return; |
2271 | |||
2272 | switch (ifsta->state) { | ||
2273 | case IEEE80211_STA_MLME_DISABLED: | ||
2274 | break; | ||
2275 | case IEEE80211_STA_MLME_DIRECT_PROBE: | ||
2276 | ieee80211_direct_probe(sdata, ifsta); | ||
2277 | break; | ||
2278 | case IEEE80211_STA_MLME_AUTHENTICATE: | ||
2279 | ieee80211_authenticate(sdata, ifsta); | ||
2280 | break; | ||
2281 | case IEEE80211_STA_MLME_ASSOCIATE: | ||
2282 | ieee80211_associate(sdata, ifsta); | ||
2283 | break; | ||
2284 | case IEEE80211_STA_MLME_ASSOCIATED: | ||
2285 | ieee80211_associated(sdata, ifsta); | ||
2286 | break; | ||
2287 | case IEEE80211_STA_MLME_IBSS_SEARCH: | ||
2288 | ieee80211_sta_find_ibss(sdata, ifsta); | ||
2289 | break; | ||
2290 | case IEEE80211_STA_MLME_IBSS_JOINED: | ||
2291 | ieee80211_sta_merge_ibss(sdata, ifsta); | ||
2292 | break; | ||
2293 | default: | ||
2294 | WARN_ON(1); | ||
2295 | break; | ||
3839 | } | 2296 | } |
3840 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
3841 | 2297 | ||
3842 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | 2298 | if (ieee80211_privacy_mismatch(sdata, ifsta)) { |
3843 | memset(nullfunc, 0, 24); | 2299 | printk(KERN_DEBUG "%s: privacy configuration mismatch and " |
3844 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | 2300 | "mixed-cell disabled - disassociate\n", sdata->dev->name); |
3845 | IEEE80211_FCTL_TODS); | ||
3846 | if (powersave) | ||
3847 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
3848 | nullfunc->frame_control = fc; | ||
3849 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); | ||
3850 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | ||
3851 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); | ||
3852 | |||
3853 | ieee80211_sta_tx(sdata->dev, skb, 0); | ||
3854 | } | ||
3855 | 2301 | ||
2302 | ieee80211_set_disassoc(sdata, ifsta, false, true, | ||
2303 | WLAN_REASON_UNSPECIFIED); | ||
2304 | } | ||
2305 | } | ||
3856 | 2306 | ||
3857 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | 2307 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
3858 | { | 2308 | { |
3859 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 2309 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
3860 | ieee80211_vif_is_mesh(&sdata->vif)) | 2310 | queue_work(sdata->local->hw.workqueue, |
3861 | ieee80211_sta_timer((unsigned long)sdata); | 2311 | &sdata->u.sta.work); |
3862 | } | 2312 | } |
3863 | 2313 | ||
3864 | void ieee80211_scan_completed(struct ieee80211_hw *hw) | 2314 | /* interface setup */ |
2315 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | ||
3865 | { | 2316 | { |
3866 | struct ieee80211_local *local = hw_to_local(hw); | 2317 | struct ieee80211_if_sta *ifsta; |
3867 | struct net_device *dev = local->scan_dev; | ||
3868 | struct ieee80211_sub_if_data *sdata; | ||
3869 | union iwreq_data wrqu; | ||
3870 | 2318 | ||
3871 | local->last_scan_completed = jiffies; | 2319 | ifsta = &sdata->u.sta; |
3872 | memset(&wrqu, 0, sizeof(wrqu)); | 2320 | INIT_WORK(&ifsta->work, ieee80211_sta_work); |
3873 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | 2321 | setup_timer(&ifsta->timer, ieee80211_sta_timer, |
3874 | 2322 | (unsigned long) sdata); | |
3875 | if (local->sta_hw_scanning) { | 2323 | skb_queue_head_init(&ifsta->skb_queue); |
3876 | local->sta_hw_scanning = 0; | ||
3877 | if (ieee80211_hw_config(local)) | ||
3878 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
3879 | "channel after scan\n", dev->name); | ||
3880 | /* Restart STA timer for HW scan case */ | ||
3881 | rcu_read_lock(); | ||
3882 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
3883 | ieee80211_restart_sta_timer(sdata); | ||
3884 | rcu_read_unlock(); | ||
3885 | 2324 | ||
3886 | goto done; | 2325 | ifsta->capab = WLAN_CAPABILITY_ESS; |
2326 | ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | | ||
2327 | IEEE80211_AUTH_ALG_SHARED_KEY; | ||
2328 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | ||
2329 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
2330 | IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
2331 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | ||
2332 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | ||
2333 | } | ||
2334 | |||
2335 | /* | ||
2336 | * Add a new IBSS station, will also be called by the RX code when, | ||
2337 | * in IBSS mode, receiving a frame from a yet-unknown station, hence | ||
2338 | * must be callable in atomic context. | ||
2339 | */ | ||
2340 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | ||
2341 | struct sk_buff *skb, u8 *bssid, | ||
2342 | u8 *addr, u64 supp_rates) | ||
2343 | { | ||
2344 | struct ieee80211_local *local = sdata->local; | ||
2345 | struct sta_info *sta; | ||
2346 | DECLARE_MAC_BUF(mac); | ||
2347 | int band = local->hw.conf.channel->band; | ||
2348 | |||
2349 | /* TODO: Could consider removing the least recently used entry and | ||
2350 | * allow new one to be added. */ | ||
2351 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | ||
2352 | if (net_ratelimit()) { | ||
2353 | printk(KERN_DEBUG "%s: No room for a new IBSS STA " | ||
2354 | "entry %s\n", sdata->dev->name, print_mac(mac, addr)); | ||
2355 | } | ||
2356 | return NULL; | ||
3887 | } | 2357 | } |
3888 | 2358 | ||
3889 | local->sta_sw_scanning = 0; | 2359 | if (compare_ether_addr(bssid, sdata->u.sta.bssid)) |
3890 | if (ieee80211_hw_config(local)) | 2360 | return NULL; |
3891 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
3892 | "channel after scan\n", dev->name); | ||
3893 | 2361 | ||
2362 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
2363 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", | ||
2364 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name); | ||
2365 | #endif | ||
3894 | 2366 | ||
3895 | netif_tx_lock_bh(local->mdev); | 2367 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
3896 | netif_addr_lock(local->mdev); | 2368 | if (!sta) |
3897 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | 2369 | return NULL; |
3898 | local->ops->configure_filter(local_to_hw(local), | ||
3899 | FIF_BCN_PRBRESP_PROMISC, | ||
3900 | &local->filter_flags, | ||
3901 | local->mdev->mc_count, | ||
3902 | local->mdev->mc_list); | ||
3903 | 2370 | ||
3904 | netif_addr_unlock(local->mdev); | 2371 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); |
3905 | netif_tx_unlock_bh(local->mdev); | ||
3906 | 2372 | ||
3907 | rcu_read_lock(); | 2373 | /* make sure mandatory rates are always added */ |
3908 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2374 | sta->sta.supp_rates[band] = supp_rates | |
3909 | /* Tell AP we're back */ | 2375 | ieee80211_mandatory_rates(local, band); |
3910 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | ||
3911 | sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) | ||
3912 | ieee80211_send_nullfunc(local, sdata, 0); | ||
3913 | 2376 | ||
3914 | ieee80211_restart_sta_timer(sdata); | 2377 | rate_control_rate_init(sta); |
3915 | 2378 | ||
3916 | netif_wake_queue(sdata->dev); | 2379 | if (sta_info_insert(sta)) |
3917 | } | 2380 | return NULL; |
3918 | rcu_read_unlock(); | ||
3919 | 2381 | ||
3920 | done: | 2382 | return sta; |
3921 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3922 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
3923 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
3924 | if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || | ||
3925 | (!(ifsta->state == IEEE80211_IBSS_JOINED) && | ||
3926 | !ieee80211_sta_active_ibss(dev))) | ||
3927 | ieee80211_sta_find_ibss(dev, ifsta); | ||
3928 | } | ||
3929 | } | 2383 | } |
3930 | EXPORT_SYMBOL(ieee80211_scan_completed); | ||
3931 | 2384 | ||
3932 | void ieee80211_sta_scan_work(struct work_struct *work) | 2385 | /* configuration hooks */ |
2386 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, | ||
2387 | struct ieee80211_if_sta *ifsta) | ||
3933 | { | 2388 | { |
3934 | struct ieee80211_local *local = | 2389 | struct ieee80211_local *local = sdata->local; |
3935 | container_of(work, struct ieee80211_local, scan_work.work); | ||
3936 | struct net_device *dev = local->scan_dev; | ||
3937 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3938 | struct ieee80211_supported_band *sband; | ||
3939 | struct ieee80211_channel *chan; | ||
3940 | int skip; | ||
3941 | unsigned long next_delay = 0; | ||
3942 | 2390 | ||
3943 | if (!local->sta_sw_scanning) | 2391 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
3944 | return; | 2392 | return; |
3945 | 2393 | ||
3946 | switch (local->scan_state) { | 2394 | if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | |
3947 | case SCAN_SET_CHANNEL: | 2395 | IEEE80211_STA_AUTO_BSSID_SEL)) && |
3948 | /* | 2396 | (ifsta->flags & (IEEE80211_STA_SSID_SET | |
3949 | * Get current scan band. scan_band may be IEEE80211_NUM_BANDS | 2397 | IEEE80211_STA_AUTO_SSID_SEL))) { |
3950 | * after we successfully scanned the last channel of the last | ||
3951 | * band (and the last band is supported by the hw) | ||
3952 | */ | ||
3953 | if (local->scan_band < IEEE80211_NUM_BANDS) | ||
3954 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
3955 | else | ||
3956 | sband = NULL; | ||
3957 | |||
3958 | /* | ||
3959 | * If we are at an unsupported band and have more bands | ||
3960 | * left to scan, advance to the next supported one. | ||
3961 | */ | ||
3962 | while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { | ||
3963 | local->scan_band++; | ||
3964 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
3965 | local->scan_channel_idx = 0; | ||
3966 | } | ||
3967 | |||
3968 | /* if no more bands/channels left, complete scan */ | ||
3969 | if (!sband || local->scan_channel_idx >= sband->n_channels) { | ||
3970 | ieee80211_scan_completed(local_to_hw(local)); | ||
3971 | return; | ||
3972 | } | ||
3973 | skip = 0; | ||
3974 | chan = &sband->channels[local->scan_channel_idx]; | ||
3975 | |||
3976 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
3977 | (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | ||
3978 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
3979 | skip = 1; | ||
3980 | |||
3981 | if (!skip) { | ||
3982 | local->scan_channel = chan; | ||
3983 | if (ieee80211_hw_config(local)) { | ||
3984 | printk(KERN_DEBUG "%s: failed to set freq to " | ||
3985 | "%d MHz for scan\n", dev->name, | ||
3986 | chan->center_freq); | ||
3987 | skip = 1; | ||
3988 | } | ||
3989 | } | ||
3990 | |||
3991 | /* advance state machine to next channel/band */ | ||
3992 | local->scan_channel_idx++; | ||
3993 | if (local->scan_channel_idx >= sband->n_channels) { | ||
3994 | /* | ||
3995 | * scan_band may end up == IEEE80211_NUM_BANDS, but | ||
3996 | * we'll catch that case above and complete the scan | ||
3997 | * if that is the case. | ||
3998 | */ | ||
3999 | local->scan_band++; | ||
4000 | local->scan_channel_idx = 0; | ||
4001 | } | ||
4002 | |||
4003 | if (skip) | ||
4004 | break; | ||
4005 | 2398 | ||
4006 | next_delay = IEEE80211_PROBE_DELAY + | 2399 | if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) |
4007 | usecs_to_jiffies(local->hw.channel_change_time); | 2400 | ieee80211_set_disassoc(sdata, ifsta, true, true, |
4008 | local->scan_state = SCAN_SEND_PROBE; | 2401 | WLAN_REASON_DEAUTH_LEAVING); |
4009 | break; | ||
4010 | case SCAN_SEND_PROBE: | ||
4011 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
4012 | local->scan_state = SCAN_SET_CHANNEL; | ||
4013 | 2402 | ||
4014 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 2403 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); |
4015 | break; | 2404 | queue_work(local->hw.workqueue, &ifsta->work); |
4016 | ieee80211_send_probe_req(dev, NULL, local->scan_ssid, | ||
4017 | local->scan_ssid_len); | ||
4018 | next_delay = IEEE80211_CHANNEL_TIME; | ||
4019 | break; | ||
4020 | } | 2405 | } |
4021 | |||
4022 | if (local->sta_sw_scanning) | ||
4023 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
4024 | next_delay); | ||
4025 | } | 2406 | } |
4026 | 2407 | ||
4027 | 2408 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) | |
4028 | static int ieee80211_sta_start_scan(struct net_device *dev, | ||
4029 | u8 *ssid, size_t ssid_len) | ||
4030 | { | 2409 | { |
4031 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2410 | struct ieee80211_if_sta *ifsta; |
4032 | struct ieee80211_sub_if_data *sdata; | 2411 | int res; |
4033 | 2412 | ||
4034 | if (ssid_len > IEEE80211_MAX_SSID_LEN) | 2413 | if (len > IEEE80211_MAX_SSID_LEN) |
4035 | return -EINVAL; | 2414 | return -EINVAL; |
4036 | 2415 | ||
4037 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) | 2416 | ifsta = &sdata->u.sta; |
4038 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS | ||
4039 | * BSSID: MACAddress | ||
4040 | * SSID | ||
4041 | * ScanType: ACTIVE, PASSIVE | ||
4042 | * ProbeDelay: delay (in microseconds) to be used prior to transmitting | ||
4043 | * a Probe frame during active scanning | ||
4044 | * ChannelList | ||
4045 | * MinChannelTime (>= ProbeDelay), in TU | ||
4046 | * MaxChannelTime: (>= MinChannelTime), in TU | ||
4047 | */ | ||
4048 | |||
4049 | /* MLME-SCAN.confirm | ||
4050 | * BSSDescriptionSet | ||
4051 | * ResultCode: SUCCESS, INVALID_PARAMETERS | ||
4052 | */ | ||
4053 | 2417 | ||
4054 | if (local->sta_sw_scanning || local->sta_hw_scanning) { | 2418 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { |
4055 | if (local->scan_dev == dev) | 2419 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); |
4056 | return 0; | 2420 | memcpy(ifsta->ssid, ssid, len); |
4057 | return -EBUSY; | 2421 | ifsta->ssid_len = len; |
4058 | } | 2422 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
4059 | 2423 | ||
4060 | if (local->ops->hw_scan) { | 2424 | res = 0; |
4061 | int rc = local->ops->hw_scan(local_to_hw(local), | 2425 | /* |
4062 | ssid, ssid_len); | 2426 | * Hack! MLME code needs to be cleaned up to have different |
4063 | if (!rc) { | 2427 | * entry points for configuration and internal selection change |
4064 | local->sta_hw_scanning = 1; | 2428 | */ |
4065 | local->scan_dev = dev; | 2429 | if (netif_running(sdata->dev)) |
2430 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
2431 | if (res) { | ||
2432 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
2433 | "the low-level driver\n", sdata->dev->name); | ||
2434 | return res; | ||
4066 | } | 2435 | } |
4067 | return rc; | ||
4068 | } | 2436 | } |
4069 | 2437 | ||
4070 | local->sta_sw_scanning = 1; | 2438 | if (len) |
2439 | ifsta->flags |= IEEE80211_STA_SSID_SET; | ||
2440 | else | ||
2441 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | ||
4071 | 2442 | ||
4072 | rcu_read_lock(); | 2443 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
4073 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2444 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { |
4074 | netif_stop_queue(sdata->dev); | 2445 | ifsta->ibss_join_req = jiffies; |
4075 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 2446 | ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; |
4076 | (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) | 2447 | return ieee80211_sta_find_ibss(sdata, ifsta); |
4077 | ieee80211_send_nullfunc(local, sdata, 1); | ||
4078 | } | 2448 | } |
4079 | rcu_read_unlock(); | ||
4080 | |||
4081 | if (ssid) { | ||
4082 | local->scan_ssid_len = ssid_len; | ||
4083 | memcpy(local->scan_ssid, ssid, ssid_len); | ||
4084 | } else | ||
4085 | local->scan_ssid_len = 0; | ||
4086 | local->scan_state = SCAN_SET_CHANNEL; | ||
4087 | local->scan_channel_idx = 0; | ||
4088 | local->scan_band = IEEE80211_BAND_2GHZ; | ||
4089 | local->scan_dev = dev; | ||
4090 | |||
4091 | netif_addr_lock_bh(local->mdev); | ||
4092 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
4093 | local->ops->configure_filter(local_to_hw(local), | ||
4094 | FIF_BCN_PRBRESP_PROMISC, | ||
4095 | &local->filter_flags, | ||
4096 | local->mdev->mc_count, | ||
4097 | local->mdev->mc_list); | ||
4098 | netif_addr_unlock_bh(local->mdev); | ||
4099 | |||
4100 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
4101 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
4102 | IEEE80211_CHANNEL_TIME); | ||
4103 | 2449 | ||
4104 | return 0; | 2450 | return 0; |
4105 | } | 2451 | } |
4106 | 2452 | ||
4107 | 2453 | int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) | |
4108 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) | ||
4109 | { | 2454 | { |
4110 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4111 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2455 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4112 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2456 | memcpy(ssid, ifsta->ssid, ifsta->ssid_len); |
4113 | 2457 | *len = ifsta->ssid_len; | |
4114 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
4115 | return ieee80211_sta_start_scan(dev, ssid, ssid_len); | ||
4116 | |||
4117 | if (local->sta_sw_scanning || local->sta_hw_scanning) { | ||
4118 | if (local->scan_dev == dev) | ||
4119 | return 0; | ||
4120 | return -EBUSY; | ||
4121 | } | ||
4122 | |||
4123 | ifsta->scan_ssid_len = ssid_len; | ||
4124 | if (ssid_len) | ||
4125 | memcpy(ifsta->scan_ssid, ssid, ssid_len); | ||
4126 | set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); | ||
4127 | queue_work(local->hw.workqueue, &ifsta->work); | ||
4128 | return 0; | 2458 | return 0; |
4129 | } | 2459 | } |
4130 | 2460 | ||
4131 | static char * | 2461 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) |
4132 | ieee80211_sta_scan_result(struct net_device *dev, | ||
4133 | struct iw_request_info *info, | ||
4134 | struct ieee80211_sta_bss *bss, | ||
4135 | char *current_ev, char *end_buf) | ||
4136 | { | 2462 | { |
4137 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2463 | struct ieee80211_if_sta *ifsta; |
4138 | struct iw_event iwe; | 2464 | int res; |
4139 | |||
4140 | if (time_after(jiffies, | ||
4141 | bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
4142 | return current_ev; | ||
4143 | |||
4144 | memset(&iwe, 0, sizeof(iwe)); | ||
4145 | iwe.cmd = SIOCGIWAP; | ||
4146 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
4147 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | ||
4148 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4149 | IW_EV_ADDR_LEN); | ||
4150 | |||
4151 | memset(&iwe, 0, sizeof(iwe)); | ||
4152 | iwe.cmd = SIOCGIWESSID; | ||
4153 | if (bss_mesh_cfg(bss)) { | ||
4154 | iwe.u.data.length = bss_mesh_id_len(bss); | ||
4155 | iwe.u.data.flags = 1; | ||
4156 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4157 | &iwe, bss_mesh_id(bss)); | ||
4158 | } else { | ||
4159 | iwe.u.data.length = bss->ssid_len; | ||
4160 | iwe.u.data.flags = 1; | ||
4161 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4162 | &iwe, bss->ssid); | ||
4163 | } | ||
4164 | |||
4165 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | ||
4166 | || bss_mesh_cfg(bss)) { | ||
4167 | memset(&iwe, 0, sizeof(iwe)); | ||
4168 | iwe.cmd = SIOCGIWMODE; | ||
4169 | if (bss_mesh_cfg(bss)) | ||
4170 | iwe.u.mode = IW_MODE_MESH; | ||
4171 | else if (bss->capability & WLAN_CAPABILITY_ESS) | ||
4172 | iwe.u.mode = IW_MODE_MASTER; | ||
4173 | else | ||
4174 | iwe.u.mode = IW_MODE_ADHOC; | ||
4175 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
4176 | &iwe, IW_EV_UINT_LEN); | ||
4177 | } | ||
4178 | |||
4179 | memset(&iwe, 0, sizeof(iwe)); | ||
4180 | iwe.cmd = SIOCGIWFREQ; | ||
4181 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | ||
4182 | iwe.u.freq.e = 0; | ||
4183 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4184 | IW_EV_FREQ_LEN); | ||
4185 | |||
4186 | memset(&iwe, 0, sizeof(iwe)); | ||
4187 | iwe.cmd = SIOCGIWFREQ; | ||
4188 | iwe.u.freq.m = bss->freq; | ||
4189 | iwe.u.freq.e = 6; | ||
4190 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4191 | IW_EV_FREQ_LEN); | ||
4192 | memset(&iwe, 0, sizeof(iwe)); | ||
4193 | iwe.cmd = IWEVQUAL; | ||
4194 | iwe.u.qual.qual = bss->qual; | ||
4195 | iwe.u.qual.level = bss->signal; | ||
4196 | iwe.u.qual.noise = bss->noise; | ||
4197 | iwe.u.qual.updated = local->wstats_flags; | ||
4198 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4199 | IW_EV_QUAL_LEN); | ||
4200 | |||
4201 | memset(&iwe, 0, sizeof(iwe)); | ||
4202 | iwe.cmd = SIOCGIWENCODE; | ||
4203 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | ||
4204 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
4205 | else | ||
4206 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
4207 | iwe.u.data.length = 0; | ||
4208 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4209 | &iwe, ""); | ||
4210 | |||
4211 | if (bss && bss->wpa_ie) { | ||
4212 | memset(&iwe, 0, sizeof(iwe)); | ||
4213 | iwe.cmd = IWEVGENIE; | ||
4214 | iwe.u.data.length = bss->wpa_ie_len; | ||
4215 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4216 | &iwe, bss->wpa_ie); | ||
4217 | } | ||
4218 | |||
4219 | if (bss && bss->rsn_ie) { | ||
4220 | memset(&iwe, 0, sizeof(iwe)); | ||
4221 | iwe.cmd = IWEVGENIE; | ||
4222 | iwe.u.data.length = bss->rsn_ie_len; | ||
4223 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4224 | &iwe, bss->rsn_ie); | ||
4225 | } | ||
4226 | |||
4227 | if (bss && bss->ht_ie) { | ||
4228 | memset(&iwe, 0, sizeof(iwe)); | ||
4229 | iwe.cmd = IWEVGENIE; | ||
4230 | iwe.u.data.length = bss->ht_ie_len; | ||
4231 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4232 | &iwe, bss->ht_ie); | ||
4233 | } | ||
4234 | |||
4235 | if (bss && bss->supp_rates_len > 0) { | ||
4236 | /* display all supported rates in readable format */ | ||
4237 | char *p = current_ev + iwe_stream_lcp_len(info); | ||
4238 | int i; | ||
4239 | |||
4240 | memset(&iwe, 0, sizeof(iwe)); | ||
4241 | iwe.cmd = SIOCGIWRATE; | ||
4242 | /* Those two flags are ignored... */ | ||
4243 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
4244 | |||
4245 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
4246 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | ||
4247 | 0x7f) * 500000); | ||
4248 | p = iwe_stream_add_value(info, current_ev, p, | ||
4249 | end_buf, &iwe, IW_EV_PARAM_LEN); | ||
4250 | } | ||
4251 | current_ev = p; | ||
4252 | } | ||
4253 | 2465 | ||
4254 | if (bss) { | 2466 | ifsta = &sdata->u.sta; |
4255 | char *buf; | ||
4256 | buf = kmalloc(30, GFP_ATOMIC); | ||
4257 | if (buf) { | ||
4258 | memset(&iwe, 0, sizeof(iwe)); | ||
4259 | iwe.cmd = IWEVCUSTOM; | ||
4260 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | ||
4261 | iwe.u.data.length = strlen(buf); | ||
4262 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4263 | end_buf, | ||
4264 | &iwe, buf); | ||
4265 | memset(&iwe, 0, sizeof(iwe)); | ||
4266 | iwe.cmd = IWEVCUSTOM; | ||
4267 | sprintf(buf, " Last beacon: %dms ago", | ||
4268 | jiffies_to_msecs(jiffies - bss->last_update)); | ||
4269 | iwe.u.data.length = strlen(buf); | ||
4270 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4271 | end_buf, &iwe, buf); | ||
4272 | kfree(buf); | ||
4273 | } | ||
4274 | } | ||
4275 | 2467 | ||
4276 | if (bss_mesh_cfg(bss)) { | 2468 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { |
4277 | char *buf; | 2469 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
4278 | u8 *cfg = bss_mesh_cfg(bss); | 2470 | res = 0; |
4279 | buf = kmalloc(50, GFP_ATOMIC); | 2471 | /* |
4280 | if (buf) { | 2472 | * Hack! See also ieee80211_sta_set_ssid. |
4281 | memset(&iwe, 0, sizeof(iwe)); | 2473 | */ |
4282 | iwe.cmd = IWEVCUSTOM; | 2474 | if (netif_running(sdata->dev)) |
4283 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | 2475 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
4284 | iwe.u.data.length = strlen(buf); | 2476 | if (res) { |
4285 | current_ev = iwe_stream_add_point(info, current_ev, | 2477 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " |
4286 | end_buf, | 2478 | "the low-level driver\n", sdata->dev->name); |
4287 | &iwe, buf); | 2479 | return res; |
4288 | sprintf(buf, "Path Selection Protocol ID: " | ||
4289 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | ||
4290 | cfg[4]); | ||
4291 | iwe.u.data.length = strlen(buf); | ||
4292 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4293 | end_buf, | ||
4294 | &iwe, buf); | ||
4295 | sprintf(buf, "Path Selection Metric ID: " | ||
4296 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | ||
4297 | cfg[8]); | ||
4298 | iwe.u.data.length = strlen(buf); | ||
4299 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4300 | end_buf, | ||
4301 | &iwe, buf); | ||
4302 | sprintf(buf, "Congestion Control Mode ID: " | ||
4303 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
4304 | cfg[11], cfg[12]); | ||
4305 | iwe.u.data.length = strlen(buf); | ||
4306 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4307 | end_buf, | ||
4308 | &iwe, buf); | ||
4309 | sprintf(buf, "Channel Precedence: " | ||
4310 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | ||
4311 | cfg[15], cfg[16]); | ||
4312 | iwe.u.data.length = strlen(buf); | ||
4313 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4314 | end_buf, | ||
4315 | &iwe, buf); | ||
4316 | kfree(buf); | ||
4317 | } | 2480 | } |
4318 | } | 2481 | } |
4319 | 2482 | ||
4320 | return current_ev; | 2483 | if (is_valid_ether_addr(bssid)) |
4321 | } | 2484 | ifsta->flags |= IEEE80211_STA_BSSID_SET; |
4322 | 2485 | else | |
2486 | ifsta->flags &= ~IEEE80211_STA_BSSID_SET; | ||
4323 | 2487 | ||
4324 | int ieee80211_sta_scan_results(struct net_device *dev, | 2488 | return 0; |
4325 | struct iw_request_info *info, | ||
4326 | char *buf, size_t len) | ||
4327 | { | ||
4328 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
4329 | char *current_ev = buf; | ||
4330 | char *end_buf = buf + len; | ||
4331 | struct ieee80211_sta_bss *bss; | ||
4332 | |||
4333 | spin_lock_bh(&local->sta_bss_lock); | ||
4334 | list_for_each_entry(bss, &local->sta_bss_list, list) { | ||
4335 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | ||
4336 | spin_unlock_bh(&local->sta_bss_lock); | ||
4337 | return -E2BIG; | ||
4338 | } | ||
4339 | current_ev = ieee80211_sta_scan_result(dev, info, bss, | ||
4340 | current_ev, end_buf); | ||
4341 | } | ||
4342 | spin_unlock_bh(&local->sta_bss_lock); | ||
4343 | return current_ev - buf; | ||
4344 | } | 2489 | } |
4345 | 2490 | ||
4346 | 2491 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) | |
4347 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | ||
4348 | { | 2492 | { |
4349 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4350 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2493 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4351 | 2494 | ||
4352 | kfree(ifsta->extra_ie); | 2495 | kfree(ifsta->extra_ie); |
@@ -4365,92 +2508,60 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | |||
4365 | return 0; | 2508 | return 0; |
4366 | } | 2509 | } |
4367 | 2510 | ||
4368 | 2511 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) | |
4369 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | ||
4370 | struct sk_buff *skb, u8 *bssid, | ||
4371 | u8 *addr, u64 supp_rates) | ||
4372 | { | ||
4373 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
4374 | struct sta_info *sta; | ||
4375 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4376 | DECLARE_MAC_BUF(mac); | ||
4377 | int band = local->hw.conf.channel->band; | ||
4378 | |||
4379 | /* TODO: Could consider removing the least recently used entry and | ||
4380 | * allow new one to be added. */ | ||
4381 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | ||
4382 | if (net_ratelimit()) { | ||
4383 | printk(KERN_DEBUG "%s: No room for a new IBSS STA " | ||
4384 | "entry %s\n", dev->name, print_mac(mac, addr)); | ||
4385 | } | ||
4386 | return NULL; | ||
4387 | } | ||
4388 | |||
4389 | if (compare_ether_addr(bssid, sdata->u.sta.bssid)) | ||
4390 | return NULL; | ||
4391 | |||
4392 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
4393 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", | ||
4394 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); | ||
4395 | #endif | ||
4396 | |||
4397 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | ||
4398 | if (!sta) | ||
4399 | return NULL; | ||
4400 | |||
4401 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
4402 | |||
4403 | if (supp_rates) | ||
4404 | sta->supp_rates[band] = supp_rates; | ||
4405 | else | ||
4406 | sta->supp_rates[band] = sdata->u.sta.supp_rates_bits[band]; | ||
4407 | |||
4408 | rate_control_rate_init(sta, local); | ||
4409 | |||
4410 | if (sta_info_insert(sta)) | ||
4411 | return NULL; | ||
4412 | |||
4413 | return sta; | ||
4414 | } | ||
4415 | |||
4416 | |||
4417 | int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason) | ||
4418 | { | 2512 | { |
4419 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4420 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2513 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4421 | 2514 | ||
4422 | printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", | 2515 | printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", |
4423 | dev->name, reason); | 2516 | sdata->dev->name, reason); |
4424 | 2517 | ||
4425 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 2518 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
4426 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | 2519 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
4427 | return -EINVAL; | 2520 | return -EINVAL; |
4428 | 2521 | ||
4429 | ieee80211_send_deauth(dev, ifsta, reason); | 2522 | ieee80211_set_disassoc(sdata, ifsta, true, true, reason); |
4430 | ieee80211_set_disassoc(dev, ifsta, 1); | ||
4431 | return 0; | 2523 | return 0; |
4432 | } | 2524 | } |
4433 | 2525 | ||
4434 | 2526 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) | |
4435 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) | ||
4436 | { | 2527 | { |
4437 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4438 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2528 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4439 | 2529 | ||
4440 | printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", | 2530 | printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", |
4441 | dev->name, reason); | 2531 | sdata->dev->name, reason); |
4442 | 2532 | ||
4443 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 2533 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
4444 | return -EINVAL; | 2534 | return -EINVAL; |
4445 | 2535 | ||
4446 | if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) | 2536 | if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) |
4447 | return -1; | 2537 | return -1; |
4448 | 2538 | ||
4449 | ieee80211_send_disassoc(dev, ifsta, reason); | 2539 | ieee80211_set_disassoc(sdata, ifsta, false, true, reason); |
4450 | ieee80211_set_disassoc(dev, ifsta, 0); | ||
4451 | return 0; | 2540 | return 0; |
4452 | } | 2541 | } |
4453 | 2542 | ||
2543 | /* scan finished notification */ | ||
2544 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | ||
2545 | { | ||
2546 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
2547 | struct ieee80211_if_sta *ifsta; | ||
2548 | |||
2549 | if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
2550 | ifsta = &sdata->u.sta; | ||
2551 | if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || | ||
2552 | (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && | ||
2553 | !ieee80211_sta_active_ibss(sdata))) | ||
2554 | ieee80211_sta_find_ibss(sdata, ifsta); | ||
2555 | } | ||
2556 | |||
2557 | /* Restart STA timers */ | ||
2558 | rcu_read_lock(); | ||
2559 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
2560 | ieee80211_restart_sta_timer(sdata); | ||
2561 | rcu_read_unlock(); | ||
2562 | } | ||
2563 | |||
2564 | /* driver notification call */ | ||
4454 | void ieee80211_notify_mac(struct ieee80211_hw *hw, | 2565 | void ieee80211_notify_mac(struct ieee80211_hw *hw, |
4455 | enum ieee80211_notification_types notif_type) | 2566 | enum ieee80211_notification_types notif_type) |
4456 | { | 2567 | { |
@@ -4461,10 +2572,10 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, | |||
4461 | case IEEE80211_NOTIFY_RE_ASSOC: | 2572 | case IEEE80211_NOTIFY_RE_ASSOC: |
4462 | rcu_read_lock(); | 2573 | rcu_read_lock(); |
4463 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2574 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
4464 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 2575 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
4465 | continue; | 2576 | continue; |
4466 | 2577 | ||
4467 | ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); | 2578 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
4468 | } | 2579 | } |
4469 | rcu_read_unlock(); | 2580 | rcu_read_unlock(); |
4470 | break; | 2581 | break; |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0388c090dfe9..5d786720d935 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include "rate.h" | 13 | #include "rate.h" |
14 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
15 | #include "debugfs.h" | ||
15 | 16 | ||
16 | struct rate_control_alg { | 17 | struct rate_control_alg { |
17 | struct list_head list; | 18 | struct list_head list; |
@@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | |||
127 | module_put(ops->module); | 128 | module_put(ops->module); |
128 | } | 129 | } |
129 | 130 | ||
131 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
132 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | ||
133 | size_t count, loff_t *ppos) | ||
134 | { | ||
135 | struct rate_control_ref *ref = file->private_data; | ||
136 | int len = strlen(ref->ops->name); | ||
137 | |||
138 | return simple_read_from_buffer(userbuf, count, ppos, | ||
139 | ref->ops->name, len); | ||
140 | } | ||
141 | |||
142 | static const struct file_operations rcname_ops = { | ||
143 | .read = rcname_read, | ||
144 | .open = mac80211_open_file_generic, | ||
145 | }; | ||
146 | #endif | ||
147 | |||
130 | struct rate_control_ref *rate_control_alloc(const char *name, | 148 | struct rate_control_ref *rate_control_alloc(const char *name, |
131 | struct ieee80211_local *local) | 149 | struct ieee80211_local *local) |
132 | { | 150 | { |
151 | struct dentry *debugfsdir = NULL; | ||
133 | struct rate_control_ref *ref; | 152 | struct rate_control_ref *ref; |
134 | 153 | ||
135 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 154 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
136 | if (!ref) | 155 | if (!ref) |
137 | goto fail_ref; | 156 | goto fail_ref; |
138 | kref_init(&ref->kref); | 157 | kref_init(&ref->kref); |
158 | ref->local = local; | ||
139 | ref->ops = ieee80211_rate_control_ops_get(name); | 159 | ref->ops = ieee80211_rate_control_ops_get(name); |
140 | if (!ref->ops) | 160 | if (!ref->ops) |
141 | goto fail_ops; | 161 | goto fail_ops; |
142 | ref->priv = ref->ops->alloc(local); | 162 | |
163 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
164 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | ||
165 | local->debugfs.rcdir = debugfsdir; | ||
166 | local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, | ||
167 | ref, &rcname_ops); | ||
168 | #endif | ||
169 | |||
170 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | ||
143 | if (!ref->priv) | 171 | if (!ref->priv) |
144 | goto fail_priv; | 172 | goto fail_priv; |
145 | return ref; | 173 | return ref; |
@@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref) | |||
158 | 186 | ||
159 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); | 187 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); |
160 | ctrl_ref->ops->free(ctrl_ref->priv); | 188 | ctrl_ref->ops->free(ctrl_ref->priv); |
189 | |||
190 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
191 | debugfs_remove(ctrl_ref->local->debugfs.rcname); | ||
192 | ctrl_ref->local->debugfs.rcname = NULL; | ||
193 | debugfs_remove(ctrl_ref->local->debugfs.rcdir); | ||
194 | ctrl_ref->local->debugfs.rcdir = NULL; | ||
195 | #endif | ||
196 | |||
161 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | 197 | ieee80211_rate_control_ops_put(ctrl_ref->ops); |
162 | kfree(ctrl_ref); | 198 | kfree(ctrl_ref); |
163 | } | 199 | } |
164 | 200 | ||
165 | void rate_control_get_rate(struct net_device *dev, | 201 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
166 | struct ieee80211_supported_band *sband, | 202 | struct ieee80211_supported_band *sband, |
167 | struct sk_buff *skb, | 203 | struct sta_info *sta, struct sk_buff *skb, |
168 | struct rate_selection *sel) | 204 | struct rate_selection *sel) |
169 | { | 205 | { |
170 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 206 | struct rate_control_ref *ref = sdata->local->rate_ctrl; |
171 | struct rate_control_ref *ref = local->rate_ctrl; | 207 | void *priv_sta = NULL; |
172 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 208 | struct ieee80211_sta *ista = NULL; |
173 | struct sta_info *sta; | ||
174 | int i; | 209 | int i; |
175 | 210 | ||
176 | rcu_read_lock(); | ||
177 | sta = sta_info_get(local, hdr->addr1); | ||
178 | |||
179 | sel->rate_idx = -1; | 211 | sel->rate_idx = -1; |
180 | sel->nonerp_idx = -1; | 212 | sel->nonerp_idx = -1; |
181 | sel->probe_idx = -1; | 213 | sel->probe_idx = -1; |
214 | sel->max_rate_idx = sdata->max_ratectrl_rateidx; | ||
215 | |||
216 | if (sta) { | ||
217 | ista = &sta->sta; | ||
218 | priv_sta = sta->rate_ctrl_priv; | ||
219 | } | ||
220 | |||
221 | if (sta && sdata->force_unicast_rateidx > -1) | ||
222 | sel->rate_idx = sdata->force_unicast_rateidx; | ||
223 | else | ||
224 | ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); | ||
182 | 225 | ||
183 | ref->ops->get_rate(ref->priv, dev, sband, skb, sel); | 226 | if (sdata->max_ratectrl_rateidx > -1 && |
227 | sel->rate_idx > sdata->max_ratectrl_rateidx) | ||
228 | sel->rate_idx = sdata->max_ratectrl_rateidx; | ||
184 | 229 | ||
185 | BUG_ON(sel->rate_idx < 0); | 230 | BUG_ON(sel->rate_idx < 0); |
186 | 231 | ||
@@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev, | |||
191 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) | 236 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) |
192 | break; | 237 | break; |
193 | 238 | ||
194 | if (rate_supported(sta, sband->band, i) && | 239 | if (rate_supported(ista, sband->band, i) && |
195 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 240 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
196 | sel->nonerp_idx = i; | 241 | sel->nonerp_idx = i; |
197 | } | 242 | } |
198 | } | 243 | } |
199 | |||
200 | rcu_read_unlock(); | ||
201 | } | 244 | } |
202 | 245 | ||
203 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) | 246 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index ede7ab56f65b..d0092f847f82 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -19,77 +19,48 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | 21 | ||
22 | /** | ||
23 | * struct rate_selection - rate selection for rate control algos | ||
24 | * @rate: selected transmission rate index | ||
25 | * @nonerp: Non-ERP rate to use instead if ERP cannot be used | ||
26 | * @probe: rate for probing (or -1) | ||
27 | * | ||
28 | */ | ||
29 | struct rate_selection { | ||
30 | s8 rate_idx, nonerp_idx, probe_idx; | ||
31 | }; | ||
32 | |||
33 | struct rate_control_ops { | ||
34 | struct module *module; | ||
35 | const char *name; | ||
36 | void (*tx_status)(void *priv, struct net_device *dev, | ||
37 | struct sk_buff *skb); | ||
38 | void (*get_rate)(void *priv, struct net_device *dev, | ||
39 | struct ieee80211_supported_band *band, | ||
40 | struct sk_buff *skb, | ||
41 | struct rate_selection *sel); | ||
42 | void (*rate_init)(void *priv, void *priv_sta, | ||
43 | struct ieee80211_local *local, struct sta_info *sta); | ||
44 | void (*clear)(void *priv); | ||
45 | |||
46 | void *(*alloc)(struct ieee80211_local *local); | ||
47 | void (*free)(void *priv); | ||
48 | void *(*alloc_sta)(void *priv, gfp_t gfp); | ||
49 | void (*free_sta)(void *priv, void *priv_sta); | ||
50 | |||
51 | int (*add_attrs)(void *priv, struct kobject *kobj); | ||
52 | void (*remove_attrs)(void *priv, struct kobject *kobj); | ||
53 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | ||
54 | struct dentry *dir); | ||
55 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | ||
56 | }; | ||
57 | |||
58 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | ||
59 | struct rate_control_ops *ops; | 24 | struct rate_control_ops *ops; |
60 | void *priv; | 25 | void *priv; |
61 | struct kref kref; | 26 | struct kref kref; |
62 | }; | 27 | }; |
63 | 28 | ||
64 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | ||
65 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | ||
66 | |||
67 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | 29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
68 | * first available algorithm. */ | 30 | * first available algorithm. */ |
69 | struct rate_control_ref *rate_control_alloc(const char *name, | 31 | struct rate_control_ref *rate_control_alloc(const char *name, |
70 | struct ieee80211_local *local); | 32 | struct ieee80211_local *local); |
71 | void rate_control_get_rate(struct net_device *dev, | 33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
72 | struct ieee80211_supported_band *sband, | 34 | struct ieee80211_supported_band *sband, |
73 | struct sk_buff *skb, | 35 | struct sta_info *sta, struct sk_buff *skb, |
74 | struct rate_selection *sel); | 36 | struct rate_selection *sel); |
75 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | 37 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); |
76 | void rate_control_put(struct rate_control_ref *ref); | 38 | void rate_control_put(struct rate_control_ref *ref); |
77 | 39 | ||
78 | static inline void rate_control_tx_status(struct net_device *dev, | 40 | static inline void rate_control_tx_status(struct ieee80211_local *local, |
41 | struct ieee80211_supported_band *sband, | ||
42 | struct sta_info *sta, | ||
79 | struct sk_buff *skb) | 43 | struct sk_buff *skb) |
80 | { | 44 | { |
81 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
82 | struct rate_control_ref *ref = local->rate_ctrl; | 45 | struct rate_control_ref *ref = local->rate_ctrl; |
46 | struct ieee80211_sta *ista = &sta->sta; | ||
47 | void *priv_sta = sta->rate_ctrl_priv; | ||
83 | 48 | ||
84 | ref->ops->tx_status(ref->priv, dev, skb); | 49 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
85 | } | 50 | } |
86 | 51 | ||
87 | 52 | ||
88 | static inline void rate_control_rate_init(struct sta_info *sta, | 53 | static inline void rate_control_rate_init(struct sta_info *sta) |
89 | struct ieee80211_local *local) | ||
90 | { | 54 | { |
55 | struct ieee80211_local *local = sta->sdata->local; | ||
91 | struct rate_control_ref *ref = sta->rate_ctrl; | 56 | struct rate_control_ref *ref = sta->rate_ctrl; |
92 | ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta); | 57 | struct ieee80211_sta *ista = &sta->sta; |
58 | void *priv_sta = sta->rate_ctrl_priv; | ||
59 | struct ieee80211_supported_band *sband; | ||
60 | |||
61 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
62 | |||
63 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | ||
93 | } | 64 | } |
94 | 65 | ||
95 | 66 | ||
@@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local) | |||
100 | } | 71 | } |
101 | 72 | ||
102 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 73 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
74 | struct ieee80211_sta *sta, | ||
103 | gfp_t gfp) | 75 | gfp_t gfp) |
104 | { | 76 | { |
105 | return ref->ops->alloc_sta(ref->priv, gfp); | 77 | return ref->ops->alloc_sta(ref->priv, sta, gfp); |
106 | } | 78 | } |
107 | 79 | ||
108 | static inline void rate_control_free_sta(struct rate_control_ref *ref, | 80 | static inline void rate_control_free_sta(struct sta_info *sta) |
109 | void *priv) | ||
110 | { | 81 | { |
111 | ref->ops->free_sta(ref->priv, priv); | 82 | struct rate_control_ref *ref = sta->rate_ctrl; |
83 | struct ieee80211_sta *ista = &sta->sta; | ||
84 | void *priv_sta = sta->rate_ctrl_priv; | ||
85 | |||
86 | ref->ops->free_sta(ref->priv, ista, priv_sta); | ||
112 | } | 87 | } |
113 | 88 | ||
114 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) | 89 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) |
@@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
130 | #endif | 105 | #endif |
131 | } | 106 | } |
132 | 107 | ||
133 | static inline int rate_supported(struct sta_info *sta, | ||
134 | enum ieee80211_band band, | ||
135 | int index) | ||
136 | { | ||
137 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | ||
138 | } | ||
139 | |||
140 | static inline s8 | ||
141 | rate_lowest_index(struct ieee80211_local *local, | ||
142 | struct ieee80211_supported_band *sband, | ||
143 | struct sta_info *sta) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i < sband->n_bitrates; i++) | ||
148 | if (rate_supported(sta, sband->band, i)) | ||
149 | return i; | ||
150 | |||
151 | /* warn when we cannot find a rate. */ | ||
152 | WARN_ON(1); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | /* functions for rate control related to a device */ | 108 | /* functions for rate control related to a device */ |
159 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 109 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
160 | const char *name); | 110 | const char *name); |
@@ -175,4 +125,18 @@ static inline void rc80211_pid_exit(void) | |||
175 | } | 125 | } |
176 | #endif | 126 | #endif |
177 | 127 | ||
128 | #ifdef CONFIG_MAC80211_RC_MINSTREL | ||
129 | extern int rc80211_minstrel_init(void); | ||
130 | extern void rc80211_minstrel_exit(void); | ||
131 | #else | ||
132 | static inline int rc80211_minstrel_init(void) | ||
133 | { | ||
134 | return 0; | ||
135 | } | ||
136 | static inline void rc80211_minstrel_exit(void) | ||
137 | { | ||
138 | } | ||
139 | #endif | ||
140 | |||
141 | |||
178 | #endif /* IEEE80211_RATE_H */ | 142 | #endif /* IEEE80211_RATE_H */ |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c new file mode 100644 index 000000000000..f6d69dab07a3 --- /dev/null +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -0,0 +1,583 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on minstrel.c: | ||
9 | * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> | ||
10 | * Sponsored by Indranet Technologies Ltd | ||
11 | * | ||
12 | * Based on sample.c: | ||
13 | * Copyright (c) 2005 John Bicket | ||
14 | * All rights reserved. | ||
15 | * | ||
16 | * Redistribution and use in source and binary forms, with or without | ||
17 | * modification, are permitted provided that the following conditions | ||
18 | * are met: | ||
19 | * 1. Redistributions of source code must retain the above copyright | ||
20 | * notice, this list of conditions and the following disclaimer, | ||
21 | * without modification. | ||
22 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
23 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
24 | * redistribution must be conditioned upon including a substantially | ||
25 | * similar Disclaimer requirement for further binary redistribution. | ||
26 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
27 | * of any contributors may be used to endorse or promote products derived | ||
28 | * from this software without specific prior written permission. | ||
29 | * | ||
30 | * Alternatively, this software may be distributed under the terms of the | ||
31 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
32 | * Software Foundation. | ||
33 | * | ||
34 | * NO WARRANTY | ||
35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
36 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
37 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
38 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
39 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
40 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
43 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
45 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
46 | */ | ||
47 | #include <linux/netdevice.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/skbuff.h> | ||
50 | #include <linux/debugfs.h> | ||
51 | #include <linux/random.h> | ||
52 | #include <linux/ieee80211.h> | ||
53 | #include <net/mac80211.h> | ||
54 | #include "rate.h" | ||
55 | #include "rc80211_minstrel.h" | ||
56 | |||
57 | #define SAMPLE_COLUMNS 10 | ||
58 | #define SAMPLE_TBL(_mi, _idx, _col) \ | ||
59 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] | ||
60 | |||
61 | /* convert mac80211 rate index to local array index */ | ||
62 | static inline int | ||
63 | rix_to_ndx(struct minstrel_sta_info *mi, int rix) | ||
64 | { | ||
65 | int i = rix; | ||
66 | for (i = rix; i >= 0; i--) | ||
67 | if (mi->r[i].rix == rix) | ||
68 | break; | ||
69 | WARN_ON(mi->r[i].rix != rix); | ||
70 | return i; | ||
71 | } | ||
72 | |||
73 | static inline bool | ||
74 | use_low_rate(struct sk_buff *skb) | ||
75 | { | ||
76 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
77 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
78 | u16 fc; | ||
79 | |||
80 | fc = le16_to_cpu(hdr->frame_control); | ||
81 | |||
82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || | ||
83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
84 | is_multicast_ether_addr(hdr->addr1)); | ||
85 | } | ||
86 | |||
87 | |||
88 | static void | ||
89 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | ||
90 | { | ||
91 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; | ||
92 | u32 max_prob = 0, index_max_prob = 0; | ||
93 | u32 usecs; | ||
94 | u32 p; | ||
95 | int i; | ||
96 | |||
97 | mi->stats_update = jiffies; | ||
98 | for (i = 0; i < mi->n_rates; i++) { | ||
99 | struct minstrel_rate *mr = &mi->r[i]; | ||
100 | |||
101 | usecs = mr->perfect_tx_time; | ||
102 | if (!usecs) | ||
103 | usecs = 1000000; | ||
104 | |||
105 | /* To avoid rounding issues, probabilities scale from 0 (0%) | ||
106 | * to 18000 (100%) */ | ||
107 | if (mr->attempts) { | ||
108 | p = (mr->success * 18000) / mr->attempts; | ||
109 | mr->succ_hist += mr->success; | ||
110 | mr->att_hist += mr->attempts; | ||
111 | mr->cur_prob = p; | ||
112 | p = ((p * (100 - mp->ewma_level)) + (mr->probability * | ||
113 | mp->ewma_level)) / 100; | ||
114 | mr->probability = p; | ||
115 | mr->cur_tp = p * (1000000 / usecs); | ||
116 | } | ||
117 | |||
118 | mr->last_success = mr->success; | ||
119 | mr->last_attempts = mr->attempts; | ||
120 | mr->success = 0; | ||
121 | mr->attempts = 0; | ||
122 | |||
123 | /* Sample less often below the 10% chance of success. | ||
124 | * Sample less often above the 95% chance of success. */ | ||
125 | if ((mr->probability > 17100) || (mr->probability < 1800)) { | ||
126 | mr->adjusted_retry_count = mr->retry_count >> 1; | ||
127 | if (mr->adjusted_retry_count > 2) | ||
128 | mr->adjusted_retry_count = 2; | ||
129 | } else { | ||
130 | mr->adjusted_retry_count = mr->retry_count; | ||
131 | } | ||
132 | if (!mr->adjusted_retry_count) | ||
133 | mr->adjusted_retry_count = 2; | ||
134 | } | ||
135 | |||
136 | for (i = 0; i < mi->n_rates; i++) { | ||
137 | struct minstrel_rate *mr = &mi->r[i]; | ||
138 | if (max_tp < mr->cur_tp) { | ||
139 | index_max_tp = i; | ||
140 | max_tp = mr->cur_tp; | ||
141 | } | ||
142 | if (max_prob < mr->probability) { | ||
143 | index_max_prob = i; | ||
144 | max_prob = mr->probability; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | max_tp = 0; | ||
149 | for (i = 0; i < mi->n_rates; i++) { | ||
150 | struct minstrel_rate *mr = &mi->r[i]; | ||
151 | |||
152 | if (i == index_max_tp) | ||
153 | continue; | ||
154 | |||
155 | if (max_tp < mr->cur_tp) { | ||
156 | index_max_tp2 = i; | ||
157 | max_tp = mr->cur_tp; | ||
158 | } | ||
159 | } | ||
160 | mi->max_tp_rate = index_max_tp; | ||
161 | mi->max_tp_rate2 = index_max_tp2; | ||
162 | mi->max_prob_rate = index_max_prob; | ||
163 | } | ||
164 | |||
165 | static void | ||
166 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | ||
167 | struct ieee80211_sta *sta, void *priv_sta, | ||
168 | struct sk_buff *skb) | ||
169 | { | ||
170 | struct minstrel_sta_info *mi = priv_sta; | ||
171 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
172 | struct ieee80211_tx_altrate *ar = info->status.retries; | ||
173 | struct minstrel_priv *mp = priv; | ||
174 | int i, ndx, tries; | ||
175 | int success = 0; | ||
176 | |||
177 | if (!info->status.excessive_retries) | ||
178 | success = 1; | ||
179 | |||
180 | if (!mp->has_mrr || (ar[0].rate_idx < 0)) { | ||
181 | ndx = rix_to_ndx(mi, info->tx_rate_idx); | ||
182 | tries = info->status.retry_count + 1; | ||
183 | mi->r[ndx].success += success; | ||
184 | mi->r[ndx].attempts += tries; | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | for (i = 0; i < 4; i++) { | ||
189 | if (ar[i].rate_idx < 0) | ||
190 | break; | ||
191 | |||
192 | ndx = rix_to_ndx(mi, ar[i].rate_idx); | ||
193 | mi->r[ndx].attempts += ar[i].limit + 1; | ||
194 | |||
195 | if ((i != 3) && (ar[i + 1].rate_idx < 0)) | ||
196 | mi->r[ndx].success += success; | ||
197 | } | ||
198 | |||
199 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) | ||
200 | mi->sample_count++; | ||
201 | |||
202 | if (mi->sample_deferred > 0) | ||
203 | mi->sample_deferred--; | ||
204 | } | ||
205 | |||
206 | |||
207 | static inline unsigned int | ||
208 | minstrel_get_retry_count(struct minstrel_rate *mr, | ||
209 | struct ieee80211_tx_info *info) | ||
210 | { | ||
211 | unsigned int retry = mr->adjusted_retry_count; | ||
212 | |||
213 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) | ||
214 | retry = max(2U, min(mr->retry_count_rtscts, retry)); | ||
215 | else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) | ||
216 | retry = max(2U, min(mr->retry_count_cts, retry)); | ||
217 | return retry; | ||
218 | } | ||
219 | |||
220 | |||
221 | static int | ||
222 | minstrel_get_next_sample(struct minstrel_sta_info *mi) | ||
223 | { | ||
224 | unsigned int sample_ndx; | ||
225 | sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); | ||
226 | mi->sample_idx++; | ||
227 | if (mi->sample_idx > (mi->n_rates - 2)) { | ||
228 | mi->sample_idx = 0; | ||
229 | mi->sample_column++; | ||
230 | if (mi->sample_column >= SAMPLE_COLUMNS) | ||
231 | mi->sample_column = 0; | ||
232 | } | ||
233 | return sample_ndx; | ||
234 | } | ||
235 | |||
236 | void | ||
237 | minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, | ||
238 | struct ieee80211_sta *sta, void *priv_sta, | ||
239 | struct sk_buff *skb, struct rate_selection *sel) | ||
240 | { | ||
241 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
242 | struct minstrel_sta_info *mi = priv_sta; | ||
243 | struct minstrel_priv *mp = priv; | ||
244 | struct ieee80211_tx_altrate *ar = info->control.retries; | ||
245 | unsigned int ndx, sample_ndx = 0; | ||
246 | bool mrr; | ||
247 | bool sample_slower = false; | ||
248 | bool sample = false; | ||
249 | int i, delta; | ||
250 | int mrr_ndx[3]; | ||
251 | int sample_rate; | ||
252 | |||
253 | if (!sta || !mi || use_low_rate(skb)) { | ||
254 | sel->rate_idx = rate_lowest_index(sband, sta); | ||
255 | return; | ||
256 | } | ||
257 | |||
258 | mrr = mp->has_mrr; | ||
259 | |||
260 | /* mac80211 does not allow mrr for RTS/CTS */ | ||
261 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | ||
262 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) | ||
263 | mrr = false; | ||
264 | |||
265 | if (time_after(jiffies, mi->stats_update + (mp->update_interval * | ||
266 | HZ) / 1000)) | ||
267 | minstrel_update_stats(mp, mi); | ||
268 | |||
269 | ndx = mi->max_tp_rate; | ||
270 | |||
271 | if (mrr) | ||
272 | sample_rate = mp->lookaround_rate_mrr; | ||
273 | else | ||
274 | sample_rate = mp->lookaround_rate; | ||
275 | |||
276 | mi->packet_count++; | ||
277 | delta = (mi->packet_count * sample_rate / 100) - | ||
278 | (mi->sample_count + mi->sample_deferred / 2); | ||
279 | |||
280 | /* delta > 0: sampling required */ | ||
281 | if (delta > 0) { | ||
282 | if (mi->packet_count >= 10000) { | ||
283 | mi->sample_deferred = 0; | ||
284 | mi->sample_count = 0; | ||
285 | mi->packet_count = 0; | ||
286 | } else if (delta > mi->n_rates * 2) { | ||
287 | /* With multi-rate retry, not every planned sample | ||
288 | * attempt actually gets used, due to the way the retry | ||
289 | * chain is set up - [max_tp,sample,prob,lowest] for | ||
290 | * sample_rate < max_tp. | ||
291 | * | ||
292 | * If there's too much sampling backlog and the link | ||
293 | * starts getting worse, minstrel would start bursting | ||
294 | * out lots of sampling frames, which would result | ||
295 | * in a large throughput loss. */ | ||
296 | mi->sample_count += (delta - mi->n_rates * 2); | ||
297 | } | ||
298 | |||
299 | sample_ndx = minstrel_get_next_sample(mi); | ||
300 | sample = true; | ||
301 | sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time > | ||
302 | mi->r[ndx].perfect_tx_time); | ||
303 | |||
304 | if (!sample_slower) { | ||
305 | ndx = sample_ndx; | ||
306 | mi->sample_count++; | ||
307 | } else { | ||
308 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark | ||
309 | * packets that have the sampling rate deferred to the | ||
310 | * second MRR stage. Increase the sample counter only | ||
311 | * if the deferred sample rate was actually used. | ||
312 | * Use the sample_deferred counter to make sure that | ||
313 | * the sampling is not done in large bursts */ | ||
314 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
315 | mi->sample_deferred++; | ||
316 | } | ||
317 | } | ||
318 | sel->rate_idx = mi->r[ndx].rix; | ||
319 | info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info); | ||
320 | |||
321 | if (!mrr) { | ||
322 | ar[0].rate_idx = mi->lowest_rix; | ||
323 | ar[0].limit = mp->max_retry; | ||
324 | ar[1].rate_idx = -1; | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | /* MRR setup */ | ||
329 | if (sample) { | ||
330 | if (sample_slower) | ||
331 | mrr_ndx[0] = sample_ndx; | ||
332 | else | ||
333 | mrr_ndx[0] = mi->max_tp_rate; | ||
334 | } else { | ||
335 | mrr_ndx[0] = mi->max_tp_rate2; | ||
336 | } | ||
337 | mrr_ndx[1] = mi->max_prob_rate; | ||
338 | mrr_ndx[2] = 0; | ||
339 | for (i = 0; i < 3; i++) { | ||
340 | ar[i].rate_idx = mi->r[mrr_ndx[i]].rix; | ||
341 | ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | |||
346 | static void | ||
347 | calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local, | ||
348 | struct minstrel_rate *d, struct ieee80211_rate *rate) | ||
349 | { | ||
350 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); | ||
351 | |||
352 | d->perfect_tx_time = ieee80211_frame_duration(local, 1200, | ||
353 | rate->bitrate, erp, 1); | ||
354 | d->ack_time = ieee80211_frame_duration(local, 10, | ||
355 | rate->bitrate, erp, 1); | ||
356 | } | ||
357 | |||
358 | static void | ||
359 | init_sample_table(struct minstrel_sta_info *mi) | ||
360 | { | ||
361 | unsigned int i, col, new_idx; | ||
362 | unsigned int n_srates = mi->n_rates - 1; | ||
363 | u8 rnd[8]; | ||
364 | |||
365 | mi->sample_column = 0; | ||
366 | mi->sample_idx = 0; | ||
367 | memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); | ||
368 | |||
369 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | ||
370 | for (i = 0; i < n_srates; i++) { | ||
371 | get_random_bytes(rnd, sizeof(rnd)); | ||
372 | new_idx = (i + rnd[i & 7]) % n_srates; | ||
373 | |||
374 | while (SAMPLE_TBL(mi, new_idx, col) != 0) | ||
375 | new_idx = (new_idx + 1) % n_srates; | ||
376 | |||
377 | /* Don't sample the slowest rate (i.e. slowest base | ||
378 | * rate). We must presume that the slowest rate works | ||
379 | * fine, or else other management frames will also be | ||
380 | * failing and the link will break */ | ||
381 | SAMPLE_TBL(mi, new_idx, col) = i + 1; | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | |||
386 | static void | ||
387 | minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | ||
388 | struct ieee80211_sta *sta, void *priv_sta) | ||
389 | { | ||
390 | struct minstrel_sta_info *mi = priv_sta; | ||
391 | struct minstrel_priv *mp = priv; | ||
392 | struct minstrel_rate *mr_ctl; | ||
393 | unsigned int i, n = 0; | ||
394 | unsigned int t_slot = 9; /* FIXME: get real slot time */ | ||
395 | |||
396 | mi->lowest_rix = rate_lowest_index(sband, sta); | ||
397 | mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)]; | ||
398 | mi->sp_ack_dur = mr_ctl->ack_time; | ||
399 | |||
400 | for (i = 0; i < sband->n_bitrates; i++) { | ||
401 | struct minstrel_rate *mr = &mi->r[n]; | ||
402 | unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; | ||
403 | unsigned int tx_time_single; | ||
404 | unsigned int cw = mp->cw_min; | ||
405 | |||
406 | if (!rate_supported(sta, sband->band, i)) | ||
407 | continue; | ||
408 | n++; | ||
409 | memset(mr, 0, sizeof(*mr)); | ||
410 | |||
411 | mr->rix = i; | ||
412 | mr->bitrate = sband->bitrates[i].bitrate / 5; | ||
413 | calc_rate_durations(mi, hw_to_local(mp->hw), mr, | ||
414 | &sband->bitrates[i]); | ||
415 | |||
416 | /* calculate maximum number of retransmissions before | ||
417 | * fallback (based on maximum segment size) */ | ||
418 | mr->retry_count = 1; | ||
419 | mr->retry_count_cts = 1; | ||
420 | mr->retry_count_rtscts = 1; | ||
421 | tx_time = mr->perfect_tx_time + mi->sp_ack_dur; | ||
422 | do { | ||
423 | /* add one retransmission */ | ||
424 | tx_time_single = mr->ack_time + mr->perfect_tx_time; | ||
425 | |||
426 | /* contention window */ | ||
427 | tx_time_single += t_slot + min(cw, mp->cw_max); | ||
428 | cw = (cw + 1) << 1; | ||
429 | |||
430 | tx_time += tx_time_single; | ||
431 | tx_time_cts += tx_time_single + mi->sp_ack_dur; | ||
432 | tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; | ||
433 | if ((tx_time_cts < mp->segment_size) && | ||
434 | (mr->retry_count_cts < mp->max_retry)) | ||
435 | mr->retry_count_cts++; | ||
436 | if ((tx_time_rtscts < mp->segment_size) && | ||
437 | (mr->retry_count_rtscts < mp->max_retry)) | ||
438 | mr->retry_count_rtscts++; | ||
439 | } while ((tx_time < mp->segment_size) && | ||
440 | (++mr->retry_count < mp->max_retry)); | ||
441 | mr->adjusted_retry_count = mr->retry_count; | ||
442 | } | ||
443 | |||
444 | for (i = n; i < sband->n_bitrates; i++) { | ||
445 | struct minstrel_rate *mr = &mi->r[i]; | ||
446 | mr->rix = -1; | ||
447 | } | ||
448 | |||
449 | mi->n_rates = n; | ||
450 | mi->stats_update = jiffies; | ||
451 | |||
452 | init_sample_table(mi); | ||
453 | } | ||
454 | |||
455 | static void * | ||
456 | minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | ||
457 | { | ||
458 | struct ieee80211_supported_band *sband; | ||
459 | struct minstrel_sta_info *mi; | ||
460 | struct minstrel_priv *mp = priv; | ||
461 | struct ieee80211_hw *hw = mp->hw; | ||
462 | int max_rates = 0; | ||
463 | int i; | ||
464 | |||
465 | mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); | ||
466 | if (!mi) | ||
467 | return NULL; | ||
468 | |||
469 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
470 | sband = hw->wiphy->bands[hw->conf.channel->band]; | ||
471 | if (sband->n_bitrates > max_rates) | ||
472 | max_rates = sband->n_bitrates; | ||
473 | } | ||
474 | |||
475 | mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); | ||
476 | if (!mi->r) | ||
477 | goto error; | ||
478 | |||
479 | mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); | ||
480 | if (!mi->sample_table) | ||
481 | goto error1; | ||
482 | |||
483 | mi->stats_update = jiffies; | ||
484 | return mi; | ||
485 | |||
486 | error1: | ||
487 | kfree(mi->r); | ||
488 | error: | ||
489 | kfree(mi); | ||
490 | return NULL; | ||
491 | } | ||
492 | |||
493 | static void | ||
494 | minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) | ||
495 | { | ||
496 | struct minstrel_sta_info *mi = priv_sta; | ||
497 | |||
498 | kfree(mi->sample_table); | ||
499 | kfree(mi->r); | ||
500 | kfree(mi); | ||
501 | } | ||
502 | |||
503 | static void | ||
504 | minstrel_clear(void *priv) | ||
505 | { | ||
506 | } | ||
507 | |||
508 | static void * | ||
509 | minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | ||
510 | { | ||
511 | struct minstrel_priv *mp; | ||
512 | |||
513 | mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); | ||
514 | if (!mp) | ||
515 | return NULL; | ||
516 | |||
517 | /* contention window settings | ||
518 | * Just an approximation. Using the per-queue values would complicate | ||
519 | * the calculations and is probably unnecessary */ | ||
520 | mp->cw_min = 15; | ||
521 | mp->cw_max = 1023; | ||
522 | |||
523 | /* number of packets (in %) to use for sampling other rates | ||
524 | * sample less often for non-mrr packets, because the overhead | ||
525 | * is much higher than with mrr */ | ||
526 | mp->lookaround_rate = 5; | ||
527 | mp->lookaround_rate_mrr = 10; | ||
528 | |||
529 | /* moving average weight for EWMA */ | ||
530 | mp->ewma_level = 75; | ||
531 | |||
532 | /* maximum time that the hw is allowed to stay in one MRR segment */ | ||
533 | mp->segment_size = 6000; | ||
534 | |||
535 | if (hw->max_altrate_tries > 0) | ||
536 | mp->max_retry = hw->max_altrate_tries; | ||
537 | else | ||
538 | /* safe default, does not necessarily have to match hw properties */ | ||
539 | mp->max_retry = 7; | ||
540 | |||
541 | if (hw->max_altrates >= 3) | ||
542 | mp->has_mrr = true; | ||
543 | |||
544 | mp->hw = hw; | ||
545 | mp->update_interval = 100; | ||
546 | |||
547 | return mp; | ||
548 | } | ||
549 | |||
550 | static void | ||
551 | minstrel_free(void *priv) | ||
552 | { | ||
553 | kfree(priv); | ||
554 | } | ||
555 | |||
556 | static struct rate_control_ops mac80211_minstrel = { | ||
557 | .name = "minstrel", | ||
558 | .tx_status = minstrel_tx_status, | ||
559 | .get_rate = minstrel_get_rate, | ||
560 | .rate_init = minstrel_rate_init, | ||
561 | .clear = minstrel_clear, | ||
562 | .alloc = minstrel_alloc, | ||
563 | .free = minstrel_free, | ||
564 | .alloc_sta = minstrel_alloc_sta, | ||
565 | .free_sta = minstrel_free_sta, | ||
566 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
567 | .add_sta_debugfs = minstrel_add_sta_debugfs, | ||
568 | .remove_sta_debugfs = minstrel_remove_sta_debugfs, | ||
569 | #endif | ||
570 | }; | ||
571 | |||
572 | int __init | ||
573 | rc80211_minstrel_init(void) | ||
574 | { | ||
575 | return ieee80211_rate_control_register(&mac80211_minstrel); | ||
576 | } | ||
577 | |||
578 | void | ||
579 | rc80211_minstrel_exit(void) | ||
580 | { | ||
581 | ieee80211_rate_control_unregister(&mac80211_minstrel); | ||
582 | } | ||
583 | |||
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h new file mode 100644 index 000000000000..9a90a6aee043 --- /dev/null +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __RC_MINSTREL_H | ||
10 | #define __RC_MINSTREL_H | ||
11 | |||
12 | struct minstrel_rate { | ||
13 | int bitrate; | ||
14 | int rix; | ||
15 | |||
16 | unsigned int perfect_tx_time; | ||
17 | unsigned int ack_time; | ||
18 | |||
19 | unsigned int retry_count; | ||
20 | unsigned int retry_count_cts; | ||
21 | unsigned int retry_count_rtscts; | ||
22 | unsigned int adjusted_retry_count; | ||
23 | |||
24 | u32 success; | ||
25 | u32 attempts; | ||
26 | u32 last_attempts; | ||
27 | u32 last_success; | ||
28 | |||
29 | /* parts per thousand */ | ||
30 | u32 cur_prob; | ||
31 | u32 probability; | ||
32 | |||
33 | /* per-rate throughput */ | ||
34 | u32 cur_tp; | ||
35 | u32 throughput; | ||
36 | |||
37 | u64 succ_hist; | ||
38 | u64 att_hist; | ||
39 | }; | ||
40 | |||
41 | struct minstrel_sta_info { | ||
42 | unsigned long stats_update; | ||
43 | unsigned int sp_ack_dur; | ||
44 | unsigned int rate_avg; | ||
45 | |||
46 | unsigned int lowest_rix; | ||
47 | |||
48 | unsigned int max_tp_rate; | ||
49 | unsigned int max_tp_rate2; | ||
50 | unsigned int max_prob_rate; | ||
51 | unsigned int packet_count; | ||
52 | unsigned int sample_count; | ||
53 | int sample_deferred; | ||
54 | |||
55 | unsigned int sample_idx; | ||
56 | unsigned int sample_column; | ||
57 | |||
58 | int n_rates; | ||
59 | struct minstrel_rate *r; | ||
60 | |||
61 | /* sampling table */ | ||
62 | u8 *sample_table; | ||
63 | |||
64 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
65 | struct dentry *dbg_stats; | ||
66 | #endif | ||
67 | }; | ||
68 | |||
69 | struct minstrel_priv { | ||
70 | struct ieee80211_hw *hw; | ||
71 | bool has_mrr; | ||
72 | unsigned int cw_min; | ||
73 | unsigned int cw_max; | ||
74 | unsigned int max_retry; | ||
75 | unsigned int ewma_level; | ||
76 | unsigned int segment_size; | ||
77 | unsigned int update_interval; | ||
78 | unsigned int lookaround_rate; | ||
79 | unsigned int lookaround_rate_mrr; | ||
80 | }; | ||
81 | |||
82 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | ||
83 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | ||
84 | |||
85 | #endif | ||
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c new file mode 100644 index 000000000000..0b024cd6b809 --- /dev/null +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on minstrel.c: | ||
9 | * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> | ||
10 | * Sponsored by Indranet Technologies Ltd | ||
11 | * | ||
12 | * Based on sample.c: | ||
13 | * Copyright (c) 2005 John Bicket | ||
14 | * All rights reserved. | ||
15 | * | ||
16 | * Redistribution and use in source and binary forms, with or without | ||
17 | * modification, are permitted provided that the following conditions | ||
18 | * are met: | ||
19 | * 1. Redistributions of source code must retain the above copyright | ||
20 | * notice, this list of conditions and the following disclaimer, | ||
21 | * without modification. | ||
22 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
23 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
24 | * redistribution must be conditioned upon including a substantially | ||
25 | * similar Disclaimer requirement for further binary redistribution. | ||
26 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
27 | * of any contributors may be used to endorse or promote products derived | ||
28 | * from this software without specific prior written permission. | ||
29 | * | ||
30 | * Alternatively, this software may be distributed under the terms of the | ||
31 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
32 | * Software Foundation. | ||
33 | * | ||
34 | * NO WARRANTY | ||
35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
36 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
37 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
38 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
39 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
40 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
43 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
45 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
46 | */ | ||
47 | #include <linux/netdevice.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/skbuff.h> | ||
50 | #include <linux/debugfs.h> | ||
51 | #include <linux/ieee80211.h> | ||
52 | #include <net/mac80211.h> | ||
53 | #include "rc80211_minstrel.h" | ||
54 | |||
55 | struct minstrel_stats_info { | ||
56 | struct minstrel_sta_info *mi; | ||
57 | char buf[4096]; | ||
58 | size_t len; | ||
59 | }; | ||
60 | |||
61 | static int | ||
62 | minstrel_stats_open(struct inode *inode, struct file *file) | ||
63 | { | ||
64 | struct minstrel_sta_info *mi = inode->i_private; | ||
65 | struct minstrel_stats_info *ms; | ||
66 | unsigned int i, tp, prob, eprob; | ||
67 | char *p; | ||
68 | |||
69 | ms = kmalloc(sizeof(*ms), GFP_KERNEL); | ||
70 | if (!ms) | ||
71 | return -ENOMEM; | ||
72 | |||
73 | file->private_data = ms; | ||
74 | p = ms->buf; | ||
75 | p += sprintf(p, "rate throughput ewma prob this prob " | ||
76 | "this succ/attempt success attempts\n"); | ||
77 | for (i = 0; i < mi->n_rates; i++) { | ||
78 | struct minstrel_rate *mr = &mi->r[i]; | ||
79 | |||
80 | *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; | ||
81 | *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; | ||
82 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; | ||
83 | p += sprintf(p, "%3u%s", mr->bitrate / 2, | ||
84 | (mr->bitrate & 1 ? ".5" : " ")); | ||
85 | |||
86 | tp = ((mr->cur_tp * 96) / 18000) >> 10; | ||
87 | prob = mr->cur_prob / 18; | ||
88 | eprob = mr->probability / 18; | ||
89 | |||
90 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | ||
91 | "%3u(%3u) %8llu %8llu\n", | ||
92 | tp / 10, tp % 10, | ||
93 | eprob / 10, eprob % 10, | ||
94 | prob / 10, prob % 10, | ||
95 | mr->last_success, | ||
96 | mr->last_attempts, | ||
97 | mr->succ_hist, | ||
98 | mr->att_hist); | ||
99 | } | ||
100 | p += sprintf(p, "\nTotal packet count:: ideal %d " | ||
101 | "lookaround %d\n\n", | ||
102 | mi->packet_count - mi->sample_count, | ||
103 | mi->sample_count); | ||
104 | ms->len = p - ms->buf; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int | ||
110 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) | ||
111 | { | ||
112 | struct minstrel_stats_info *ms; | ||
113 | char *src; | ||
114 | |||
115 | ms = file->private_data; | ||
116 | src = ms->buf; | ||
117 | |||
118 | len = min(len, ms->len); | ||
119 | if (len <= *o) | ||
120 | return 0; | ||
121 | |||
122 | src += *o; | ||
123 | len -= *o; | ||
124 | *o += len; | ||
125 | |||
126 | if (copy_to_user(buf, src, len)) | ||
127 | return -EFAULT; | ||
128 | |||
129 | return len; | ||
130 | } | ||
131 | |||
132 | static int | ||
133 | minstrel_stats_release(struct inode *inode, struct file *file) | ||
134 | { | ||
135 | struct minstrel_stats_info *ms = file->private_data; | ||
136 | |||
137 | kfree(ms); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static struct file_operations minstrel_stat_fops = { | ||
143 | .owner = THIS_MODULE, | ||
144 | .open = minstrel_stats_open, | ||
145 | .read = minstrel_stats_read, | ||
146 | .release = minstrel_stats_release, | ||
147 | }; | ||
148 | |||
149 | void | ||
150 | minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) | ||
151 | { | ||
152 | struct minstrel_sta_info *mi = priv_sta; | ||
153 | |||
154 | mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, | ||
155 | &minstrel_stat_fops); | ||
156 | } | ||
157 | |||
158 | void | ||
159 | minstrel_remove_sta_debugfs(void *priv, void *priv_sta) | ||
160 | { | ||
161 | struct minstrel_sta_info *mi = priv_sta; | ||
162 | |||
163 | debugfs_remove(mi->dbg_stats); | ||
164 | } | ||
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 0a9135b974b5..01d64d53f3b9 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -124,7 +124,6 @@ struct rc_pid_events_file_info { | |||
124 | * struct rc_pid_debugfs_entries - tunable parameters | 124 | * struct rc_pid_debugfs_entries - tunable parameters |
125 | * | 125 | * |
126 | * Algorithm parameters, tunable via debugfs. | 126 | * Algorithm parameters, tunable via debugfs. |
127 | * @dir: the debugfs directory for a specific phy | ||
128 | * @target: target percentage for failed frames | 127 | * @target: target percentage for failed frames |
129 | * @sampling_period: error sampling interval in milliseconds | 128 | * @sampling_period: error sampling interval in milliseconds |
130 | * @coeff_p: absolute value of the proportional coefficient | 129 | * @coeff_p: absolute value of the proportional coefficient |
@@ -143,7 +142,6 @@ struct rc_pid_events_file_info { | |||
143 | * ordering of rates) | 142 | * ordering of rates) |
144 | */ | 143 | */ |
145 | struct rc_pid_debugfs_entries { | 144 | struct rc_pid_debugfs_entries { |
146 | struct dentry *dir; | ||
147 | struct dentry *target; | 145 | struct dentry *target; |
148 | struct dentry *sampling_period; | 146 | struct dentry *sampling_period; |
149 | struct dentry *coeff_p; | 147 | struct dentry *coeff_p; |
@@ -180,6 +178,8 @@ struct rc_pid_sta_info { | |||
180 | u32 tx_num_failed; | 178 | u32 tx_num_failed; |
181 | u32 tx_num_xmit; | 179 | u32 tx_num_xmit; |
182 | 180 | ||
181 | int txrate_idx; | ||
182 | |||
183 | /* Average failed frames percentage error (i.e. actual vs. target | 183 | /* Average failed frames percentage error (i.e. actual vs. target |
184 | * percentage), scaled by RC_PID_SMOOTHING. This value is computed | 184 | * percentage), scaled by RC_PID_SMOOTHING. This value is computed |
185 | * using using an exponential weighted average technique: | 185 | * using using an exponential weighted average technique: |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a914ba73ccf5..86eb374e3b87 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -68,17 +68,14 @@ | |||
68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | 68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate |
69 | * whose failed frames behaviour is not worse than the one of the original rate | 69 | * whose failed frames behaviour is not worse than the one of the original rate |
70 | * target. While at it, check that the new rate is valid. */ | 70 | * target. While at it, check that the new rate is valid. */ |
71 | static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | 71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, |
72 | struct sta_info *sta, int adj, | 72 | struct ieee80211_sta *sta, |
73 | struct rc_pid_sta_info *spinfo, int adj, | ||
73 | struct rc_pid_rateinfo *rinfo) | 74 | struct rc_pid_rateinfo *rinfo) |
74 | { | 75 | { |
75 | struct ieee80211_sub_if_data *sdata; | ||
76 | struct ieee80211_supported_band *sband; | ||
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
78 | int cur = sta->txrate_idx; | 77 | int cur = spinfo->txrate_idx; |
79 | 78 | ||
80 | sdata = sta->sdata; | ||
81 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
82 | band = sband->band; | 79 | band = sband->band; |
83 | n_bitrates = sband->n_bitrates; | 80 | n_bitrates = sband->n_bitrates; |
84 | 81 | ||
@@ -111,7 +108,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | |||
111 | /* Fit the rate found to the nearest supported rate. */ | 108 | /* Fit the rate found to the nearest supported rate. */ |
112 | do { | 109 | do { |
113 | if (rate_supported(sta, band, rinfo[tmp].index)) { | 110 | if (rate_supported(sta, band, rinfo[tmp].index)) { |
114 | sta->txrate_idx = rinfo[tmp].index; | 111 | spinfo->txrate_idx = rinfo[tmp].index; |
115 | break; | 112 | break; |
116 | } | 113 | } |
117 | if (adj < 0) | 114 | if (adj < 0) |
@@ -121,9 +118,9 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | |||
121 | } while (tmp < n_bitrates && tmp >= 0); | 118 | } while (tmp < n_bitrates && tmp >= 0); |
122 | 119 | ||
123 | #ifdef CONFIG_MAC80211_DEBUGFS | 120 | #ifdef CONFIG_MAC80211_DEBUGFS |
124 | rate_control_pid_event_rate_change( | 121 | rate_control_pid_event_rate_change(&spinfo->events, |
125 | &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, | 122 | spinfo->txrate_idx, |
126 | sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate); | 123 | sband->bitrates[spinfo->txrate_idx].bitrate); |
127 | #endif | 124 | #endif |
128 | } | 125 | } |
129 | 126 | ||
@@ -145,15 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | |||
145 | } | 142 | } |
146 | 143 | ||
147 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | 144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, |
148 | struct ieee80211_local *local, | 145 | struct ieee80211_supported_band *sband, |
149 | struct sta_info *sta) | 146 | struct ieee80211_sta *sta, |
147 | struct rc_pid_sta_info *spinfo) | ||
150 | { | 148 | { |
151 | #ifdef CONFIG_MAC80211_MESH | ||
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
153 | #endif | ||
154 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | ||
155 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
156 | struct ieee80211_supported_band *sband; | ||
157 | u32 pf; | 150 | u32 pf; |
158 | s32 err_avg; | 151 | s32 err_avg; |
159 | u32 err_prop; | 152 | u32 err_prop; |
@@ -162,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
162 | int adj, i, j, tmp; | 155 | int adj, i, j, tmp; |
163 | unsigned long period; | 156 | unsigned long period; |
164 | 157 | ||
165 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
166 | spinfo = sta->rate_ctrl_priv; | ||
167 | |||
168 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
169 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
170 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
@@ -180,14 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
180 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
181 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
182 | else { | 172 | else { |
173 | /* XXX: BAD HACK!!! */ | ||
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | ||
175 | |||
183 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
184 | #ifdef CONFIG_MAC80211_MESH | 177 | |
185 | if (pf == 100 && | 178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) |
186 | sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) | 179 | mesh_plink_broken(si); |
187 | mesh_plink_broken(sta); | ||
188 | #endif | ||
189 | pf <<= RC_PID_ARITH_SHIFT; | 180 | pf <<= RC_PID_ARITH_SHIFT; |
190 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
191 | >> RC_PID_ARITH_SHIFT; | 182 | >> RC_PID_ARITH_SHIFT; |
192 | } | 183 | } |
193 | 184 | ||
@@ -195,16 +186,16 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
195 | spinfo->tx_num_failed = 0; | 186 | spinfo->tx_num_failed = 0; |
196 | 187 | ||
197 | /* If we just switched rate, update the rate behaviour info. */ | 188 | /* If we just switched rate, update the rate behaviour info. */ |
198 | if (pinfo->oldrate != sta->txrate_idx) { | 189 | if (pinfo->oldrate != spinfo->txrate_idx) { |
199 | 190 | ||
200 | i = rinfo[pinfo->oldrate].rev_index; | 191 | i = rinfo[pinfo->oldrate].rev_index; |
201 | j = rinfo[sta->txrate_idx].rev_index; | 192 | j = rinfo[spinfo->txrate_idx].rev_index; |
202 | 193 | ||
203 | tmp = (pf - spinfo->last_pf); | 194 | tmp = (pf - spinfo->last_pf); |
204 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); | 195 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); |
205 | 196 | ||
206 | rinfo[j].diff = rinfo[i].diff + tmp; | 197 | rinfo[j].diff = rinfo[i].diff + tmp; |
207 | pinfo->oldrate = sta->txrate_idx; | 198 | pinfo->oldrate = spinfo->txrate_idx; |
208 | } | 199 | } |
209 | rate_control_pid_normalize(pinfo, sband->n_bitrates); | 200 | rate_control_pid_normalize(pinfo, sband->n_bitrates); |
210 | 201 | ||
@@ -233,43 +224,26 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
233 | 224 | ||
234 | /* Change rate. */ | 225 | /* Change rate. */ |
235 | if (adj) | 226 | if (adj) |
236 | rate_control_pid_adjust_rate(local, sta, adj, rinfo); | 227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); |
237 | } | 228 | } |
238 | 229 | ||
239 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | 230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, |
231 | struct ieee80211_sta *sta, void *priv_sta, | ||
240 | struct sk_buff *skb) | 232 | struct sk_buff *skb) |
241 | { | 233 | { |
242 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
243 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
244 | struct ieee80211_sub_if_data *sdata; | ||
245 | struct rc_pid_info *pinfo = priv; | 234 | struct rc_pid_info *pinfo = priv; |
246 | struct sta_info *sta; | 235 | struct rc_pid_sta_info *spinfo = priv_sta; |
247 | struct rc_pid_sta_info *spinfo; | ||
248 | unsigned long period; | 236 | unsigned long period; |
249 | struct ieee80211_supported_band *sband; | ||
250 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
251 | 238 | ||
252 | rcu_read_lock(); | 239 | if (!spinfo) |
253 | 240 | return; | |
254 | sta = sta_info_get(local, hdr->addr1); | ||
255 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
256 | |||
257 | if (!sta) | ||
258 | goto unlock; | ||
259 | |||
260 | /* Don't update the state if we're not controlling the rate. */ | ||
261 | sdata = sta->sdata; | ||
262 | if (sdata->force_unicast_rateidx > -1) { | ||
263 | sta->txrate_idx = sdata->max_ratectrl_rateidx; | ||
264 | goto unlock; | ||
265 | } | ||
266 | 241 | ||
267 | /* Ignore all frames that were sent with a different rate than the rate | 242 | /* Ignore all frames that were sent with a different rate than the rate |
268 | * we currently advise mac80211 to use. */ | 243 | * we currently advise mac80211 to use. */ |
269 | if (info->tx_rate_idx != sta->txrate_idx) | 244 | if (info->tx_rate_idx != spinfo->txrate_idx) |
270 | goto unlock; | 245 | return; |
271 | 246 | ||
272 | spinfo = sta->rate_ctrl_priv; | ||
273 | spinfo->tx_num_xmit++; | 247 | spinfo->tx_num_xmit++; |
274 | 248 | ||
275 | #ifdef CONFIG_MAC80211_DEBUGFS | 249 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -287,93 +261,68 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
287 | spinfo->tx_num_xmit++; | 261 | spinfo->tx_num_xmit++; |
288 | } | 262 | } |
289 | 263 | ||
290 | if (info->status.excessive_retries) { | ||
291 | sta->tx_retry_failed++; | ||
292 | sta->tx_num_consecutive_failures++; | ||
293 | sta->tx_num_mpdu_fail++; | ||
294 | } else { | ||
295 | sta->tx_num_consecutive_failures = 0; | ||
296 | sta->tx_num_mpdu_ok++; | ||
297 | } | ||
298 | sta->tx_retry_count += info->status.retry_count; | ||
299 | sta->tx_num_mpdu_fail += info->status.retry_count; | ||
300 | |||
301 | /* Update PID controller state. */ | 264 | /* Update PID controller state. */ |
302 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 265 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
303 | if (!period) | 266 | if (!period) |
304 | period = 1; | 267 | period = 1; |
305 | if (time_after(jiffies, spinfo->last_sample + period)) | 268 | if (time_after(jiffies, spinfo->last_sample + period)) |
306 | rate_control_pid_sample(pinfo, local, sta); | 269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
307 | |||
308 | unlock: | ||
309 | rcu_read_unlock(); | ||
310 | } | 270 | } |
311 | 271 | ||
312 | static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | 272 | static void |
313 | struct ieee80211_supported_band *sband, | 273 | rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, |
314 | struct sk_buff *skb, | 274 | struct ieee80211_sta *sta, void *priv_sta, |
315 | struct rate_selection *sel) | 275 | struct sk_buff *skb, |
276 | struct rate_selection *sel) | ||
316 | { | 277 | { |
317 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
318 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 278 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
319 | struct ieee80211_sub_if_data *sdata; | 279 | struct rc_pid_sta_info *spinfo = priv_sta; |
320 | struct sta_info *sta; | ||
321 | int rateidx; | 280 | int rateidx; |
322 | u16 fc; | 281 | u16 fc; |
323 | 282 | ||
324 | rcu_read_lock(); | ||
325 | |||
326 | sta = sta_info_get(local, hdr->addr1); | ||
327 | |||
328 | /* Send management frames and broadcast/multicast data using lowest | 283 | /* Send management frames and broadcast/multicast data using lowest |
329 | * rate. */ | 284 | * rate. */ |
330 | fc = le16_to_cpu(hdr->frame_control); | 285 | fc = le16_to_cpu(hdr->frame_control); |
331 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 286 | if (!sta || !spinfo || |
332 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 287 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
333 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 288 | is_multicast_ether_addr(hdr->addr1)) { |
334 | rcu_read_unlock(); | 289 | sel->rate_idx = rate_lowest_index(sband, sta); |
335 | return; | 290 | return; |
336 | } | 291 | } |
337 | 292 | ||
338 | /* If a forced rate is in effect, select it. */ | 293 | rateidx = spinfo->txrate_idx; |
339 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
340 | if (sdata->force_unicast_rateidx > -1) | ||
341 | sta->txrate_idx = sdata->force_unicast_rateidx; | ||
342 | |||
343 | rateidx = sta->txrate_idx; | ||
344 | 294 | ||
345 | if (rateidx >= sband->n_bitrates) | 295 | if (rateidx >= sband->n_bitrates) |
346 | rateidx = sband->n_bitrates - 1; | 296 | rateidx = sband->n_bitrates - 1; |
347 | 297 | ||
348 | sta->last_txrate_idx = rateidx; | ||
349 | |||
350 | rcu_read_unlock(); | ||
351 | |||
352 | sel->rate_idx = rateidx; | 298 | sel->rate_idx = rateidx; |
353 | 299 | ||
354 | #ifdef CONFIG_MAC80211_DEBUGFS | 300 | #ifdef CONFIG_MAC80211_DEBUGFS |
355 | rate_control_pid_event_tx_rate( | 301 | rate_control_pid_event_tx_rate(&spinfo->events, |
356 | &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, | ||
357 | rateidx, sband->bitrates[rateidx].bitrate); | 302 | rateidx, sband->bitrates[rateidx].bitrate); |
358 | #endif | 303 | #endif |
359 | } | 304 | } |
360 | 305 | ||
361 | static void rate_control_pid_rate_init(void *priv, void *priv_sta, | 306 | static void |
362 | struct ieee80211_local *local, | 307 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
363 | struct sta_info *sta) | 308 | struct ieee80211_sta *sta, void *priv_sta) |
364 | { | 309 | { |
310 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
311 | struct sta_info *si; | ||
312 | |||
365 | /* TODO: This routine should consider using RSSI from previous packets | 313 | /* TODO: This routine should consider using RSSI from previous packets |
366 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | 314 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
367 | * Until that method is implemented, we will use the lowest supported | 315 | * Until that method is implemented, we will use the lowest supported |
368 | * rate as a workaround. */ | 316 | * rate as a workaround. */ |
369 | struct ieee80211_supported_band *sband; | ||
370 | 317 | ||
371 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 318 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
372 | sta->txrate_idx = rate_lowest_index(local, sband, sta); | 319 | /* HACK */ |
373 | sta->fail_avg = 0; | 320 | si = container_of(sta, struct sta_info, sta); |
321 | si->fail_avg = 0; | ||
374 | } | 322 | } |
375 | 323 | ||
376 | static void *rate_control_pid_alloc(struct ieee80211_local *local) | 324 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
325 | struct dentry *debugfsdir) | ||
377 | { | 326 | { |
378 | struct rc_pid_info *pinfo; | 327 | struct rc_pid_info *pinfo; |
379 | struct rc_pid_rateinfo *rinfo; | 328 | struct rc_pid_rateinfo *rinfo; |
@@ -384,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
384 | struct rc_pid_debugfs_entries *de; | 333 | struct rc_pid_debugfs_entries *de; |
385 | #endif | 334 | #endif |
386 | 335 | ||
387 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 336 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
388 | 337 | ||
389 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | 338 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); |
390 | if (!pinfo) | 339 | if (!pinfo) |
@@ -439,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
439 | 388 | ||
440 | #ifdef CONFIG_MAC80211_DEBUGFS | 389 | #ifdef CONFIG_MAC80211_DEBUGFS |
441 | de = &pinfo->dentries; | 390 | de = &pinfo->dentries; |
442 | de->dir = debugfs_create_dir("rc80211_pid", | ||
443 | local->hw.wiphy->debugfsdir); | ||
444 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | 391 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, |
445 | de->dir, &pinfo->target); | 392 | debugfsdir, &pinfo->target); |
446 | de->sampling_period = debugfs_create_u32("sampling_period", | 393 | de->sampling_period = debugfs_create_u32("sampling_period", |
447 | S_IRUSR | S_IWUSR, de->dir, | 394 | S_IRUSR | S_IWUSR, debugfsdir, |
448 | &pinfo->sampling_period); | 395 | &pinfo->sampling_period); |
449 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | 396 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, |
450 | de->dir, &pinfo->coeff_p); | 397 | debugfsdir, &pinfo->coeff_p); |
451 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | 398 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, |
452 | de->dir, &pinfo->coeff_i); | 399 | debugfsdir, &pinfo->coeff_i); |
453 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | 400 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, |
454 | de->dir, &pinfo->coeff_d); | 401 | debugfsdir, &pinfo->coeff_d); |
455 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | 402 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", |
456 | S_IRUSR | S_IWUSR, de->dir, | 403 | S_IRUSR | S_IWUSR, debugfsdir, |
457 | &pinfo->smoothing_shift); | 404 | &pinfo->smoothing_shift); |
458 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | 405 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", |
459 | S_IRUSR | S_IWUSR, de->dir, | 406 | S_IRUSR | S_IWUSR, debugfsdir, |
460 | &pinfo->sharpen_factor); | 407 | &pinfo->sharpen_factor); |
461 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | 408 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", |
462 | S_IRUSR | S_IWUSR, de->dir, | 409 | S_IRUSR | S_IWUSR, debugfsdir, |
463 | &pinfo->sharpen_duration); | 410 | &pinfo->sharpen_duration); |
464 | de->norm_offset = debugfs_create_u32("norm_offset", | 411 | de->norm_offset = debugfs_create_u32("norm_offset", |
465 | S_IRUSR | S_IWUSR, de->dir, | 412 | S_IRUSR | S_IWUSR, debugfsdir, |
466 | &pinfo->norm_offset); | 413 | &pinfo->norm_offset); |
467 | #endif | 414 | #endif |
468 | 415 | ||
@@ -484,7 +431,6 @@ static void rate_control_pid_free(void *priv) | |||
484 | debugfs_remove(de->coeff_p); | 431 | debugfs_remove(de->coeff_p); |
485 | debugfs_remove(de->sampling_period); | 432 | debugfs_remove(de->sampling_period); |
486 | debugfs_remove(de->target); | 433 | debugfs_remove(de->target); |
487 | debugfs_remove(de->dir); | ||
488 | #endif | 434 | #endif |
489 | 435 | ||
490 | kfree(pinfo->rinfo); | 436 | kfree(pinfo->rinfo); |
@@ -495,7 +441,8 @@ static void rate_control_pid_clear(void *priv) | |||
495 | { | 441 | { |
496 | } | 442 | } |
497 | 443 | ||
498 | static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | 444 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, |
445 | gfp_t gfp) | ||
499 | { | 446 | { |
500 | struct rc_pid_sta_info *spinfo; | 447 | struct rc_pid_sta_info *spinfo; |
501 | 448 | ||
@@ -513,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | |||
513 | return spinfo; | 460 | return spinfo; |
514 | } | 461 | } |
515 | 462 | ||
516 | static void rate_control_pid_free_sta(void *priv, void *priv_sta) | 463 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, |
464 | void *priv_sta) | ||
517 | { | 465 | { |
518 | struct rc_pid_sta_info *spinfo = priv_sta; | 466 | kfree(priv_sta); |
519 | kfree(spinfo); | ||
520 | } | 467 | } |
521 | 468 | ||
522 | static struct rate_control_ops mac80211_rcpid = { | 469 | static struct rate_control_ops mac80211_rcpid = { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6db854505193..cf6b121e1bbf 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -143,6 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
143 | /* IEEE80211_RADIOTAP_FLAGS */ | 143 | /* IEEE80211_RADIOTAP_FLAGS */ |
144 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 144 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
145 | *pos |= IEEE80211_RADIOTAP_F_FCS; | 145 | *pos |= IEEE80211_RADIOTAP_F_FCS; |
146 | if (status->flag & RX_FLAG_SHORTPRE) | ||
147 | *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
146 | pos++; | 148 | pos++; |
147 | 149 | ||
148 | /* IEEE80211_RADIOTAP_RATE */ | 150 | /* IEEE80211_RADIOTAP_RATE */ |
@@ -155,8 +157,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
155 | if (status->band == IEEE80211_BAND_5GHZ) | 157 | if (status->band == IEEE80211_BAND_5GHZ) |
156 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | 158 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | |
157 | IEEE80211_CHAN_5GHZ); | 159 | IEEE80211_CHAN_5GHZ); |
160 | else if (rate->flags & IEEE80211_RATE_ERP_G) | ||
161 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
162 | IEEE80211_CHAN_2GHZ); | ||
158 | else | 163 | else |
159 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN | | 164 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | |
160 | IEEE80211_CHAN_2GHZ); | 165 | IEEE80211_CHAN_2GHZ); |
161 | pos += 2; | 166 | pos += 2; |
162 | 167 | ||
@@ -290,7 +295,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
290 | if (!netif_running(sdata->dev)) | 295 | if (!netif_running(sdata->dev)) |
291 | continue; | 296 | continue; |
292 | 297 | ||
293 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR) | 298 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
294 | continue; | 299 | continue; |
295 | 300 | ||
296 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) | 301 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) |
@@ -398,12 +403,12 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
398 | struct ieee80211_local *local = rx->local; | 403 | struct ieee80211_local *local = rx->local; |
399 | struct sk_buff *skb = rx->skb; | 404 | struct sk_buff *skb = rx->skb; |
400 | 405 | ||
401 | if (unlikely(local->sta_hw_scanning)) | 406 | if (unlikely(local->hw_scanning)) |
402 | return ieee80211_sta_rx_scan(rx->dev, skb, rx->status); | 407 | return ieee80211_scan_rx(rx->sdata, skb, rx->status); |
403 | 408 | ||
404 | if (unlikely(local->sta_sw_scanning)) { | 409 | if (unlikely(local->sw_scanning)) { |
405 | /* drop all the other packets during a software scan anyway */ | 410 | /* drop all the other packets during a software scan anyway */ |
406 | if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status) | 411 | if (ieee80211_scan_rx(rx->sdata, skb, rx->status) |
407 | != RX_QUEUED) | 412 | != RX_QUEUED) |
408 | dev_kfree_skb(skb); | 413 | dev_kfree_skb(skb); |
409 | return RX_QUEUED; | 414 | return RX_QUEUED; |
@@ -461,7 +466,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
461 | 466 | ||
462 | if (ieee80211_is_data(hdr->frame_control) && | 467 | if (ieee80211_is_data(hdr->frame_control) && |
463 | is_multicast_ether_addr(hdr->addr1) && | 468 | is_multicast_ether_addr(hdr->addr1) && |
464 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) | 469 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) |
465 | return RX_DROP_MONITOR; | 470 | return RX_DROP_MONITOR; |
466 | #undef msh_h_get | 471 | #undef msh_h_get |
467 | 472 | ||
@@ -496,8 +501,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
496 | /* Drop disallowed frame classes based on STA auth/assoc state; | 501 | /* Drop disallowed frame classes based on STA auth/assoc state; |
497 | * IEEE 802.11, Chap 5.5. | 502 | * IEEE 802.11, Chap 5.5. |
498 | * | 503 | * |
499 | * 80211.o does filtering only based on association state, i.e., it | 504 | * mac80211 filters only based on association state, i.e. it drops |
500 | * drops Class 3 frames from not associated stations. hostapd sends | 505 | * Class 3 frames from not associated stations. hostapd sends |
501 | * deauth/disassoc frames when needed. In addition, hostapd is | 506 | * deauth/disassoc frames when needed. In addition, hostapd is |
502 | * responsible for filtering on both auth and assoc states. | 507 | * responsible for filtering on both auth and assoc states. |
503 | */ | 508 | */ |
@@ -507,7 +512,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
507 | 512 | ||
508 | if (unlikely((ieee80211_is_data(hdr->frame_control) || | 513 | if (unlikely((ieee80211_is_data(hdr->frame_control) || |
509 | ieee80211_is_pspoll(hdr->frame_control)) && | 514 | ieee80211_is_pspoll(hdr->frame_control)) && |
510 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 515 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
511 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 516 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
512 | if ((!ieee80211_has_fromds(hdr->frame_control) && | 517 | if ((!ieee80211_has_fromds(hdr->frame_control) && |
513 | !ieee80211_has_tods(hdr->frame_control) && | 518 | !ieee80211_has_tods(hdr->frame_control) && |
@@ -645,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
645 | return result; | 650 | return result; |
646 | } | 651 | } |
647 | 652 | ||
648 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | 653 | static void ap_sta_ps_start(struct sta_info *sta) |
649 | { | 654 | { |
650 | struct ieee80211_sub_if_data *sdata; | 655 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
651 | DECLARE_MAC_BUF(mac); | 656 | DECLARE_MAC_BUF(mac); |
652 | 657 | ||
653 | sdata = sta->sdata; | ||
654 | |||
655 | atomic_inc(&sdata->bss->num_sta_ps); | 658 | atomic_inc(&sdata->bss->num_sta_ps); |
656 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 659 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
657 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 660 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
658 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 661 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
659 | dev->name, print_mac(mac, sta->addr), sta->aid); | 662 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
660 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 663 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
661 | } | 664 | } |
662 | 665 | ||
663 | static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | 666 | static int ap_sta_ps_end(struct sta_info *sta) |
664 | { | 667 | { |
665 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 668 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
669 | struct ieee80211_local *local = sdata->local; | ||
666 | struct sk_buff *skb; | 670 | struct sk_buff *skb; |
667 | int sent = 0; | 671 | int sent = 0; |
668 | struct ieee80211_sub_if_data *sdata; | ||
669 | struct ieee80211_tx_info *info; | 672 | struct ieee80211_tx_info *info; |
670 | DECLARE_MAC_BUF(mac); | 673 | DECLARE_MAC_BUF(mac); |
671 | 674 | ||
672 | sdata = sta->sdata; | ||
673 | |||
674 | atomic_dec(&sdata->bss->num_sta_ps); | 675 | atomic_dec(&sdata->bss->num_sta_ps); |
675 | 676 | ||
676 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 677 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
@@ -680,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
680 | 681 | ||
681 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 682 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
682 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", | 683 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", |
683 | dev->name, print_mac(mac, sta->addr), sta->aid); | 684 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
684 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 685 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
685 | 686 | ||
686 | /* Send all buffered frames to the station */ | 687 | /* Send all buffered frames to the station */ |
@@ -696,8 +697,8 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
696 | sent++; | 697 | sent++; |
697 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 698 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
698 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " | 699 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " |
699 | "since STA not sleeping anymore\n", dev->name, | 700 | "since STA not sleeping anymore\n", sdata->dev->name, |
700 | print_mac(mac, sta->addr), sta->aid); | 701 | print_mac(mac, sta->sta.addr), sta->sta.aid); |
701 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 702 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
702 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 703 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
703 | dev_queue_xmit(skb); | 704 | dev_queue_xmit(skb); |
@@ -710,7 +711,6 @@ static ieee80211_rx_result debug_noinline | |||
710 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 711 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
711 | { | 712 | { |
712 | struct sta_info *sta = rx->sta; | 713 | struct sta_info *sta = rx->sta; |
713 | struct net_device *dev = rx->dev; | ||
714 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 714 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
715 | 715 | ||
716 | if (!sta) | 716 | if (!sta) |
@@ -719,14 +719,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
719 | /* Update last_rx only for IBSS packets which are for the current | 719 | /* Update last_rx only for IBSS packets which are for the current |
720 | * BSSID to avoid keeping the current IBSS network alive in cases where | 720 | * BSSID to avoid keeping the current IBSS network alive in cases where |
721 | * other STAs are using different BSSID. */ | 721 | * other STAs are using different BSSID. */ |
722 | if (rx->sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 722 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
723 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 723 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
724 | IEEE80211_IF_TYPE_IBSS); | 724 | NL80211_IFTYPE_ADHOC); |
725 | if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) | 725 | if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) |
726 | sta->last_rx = jiffies; | 726 | sta->last_rx = jiffies; |
727 | } else | 727 | } else |
728 | if (!is_multicast_ether_addr(hdr->addr1) || | 728 | if (!is_multicast_ether_addr(hdr->addr1) || |
729 | rx->sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 729 | rx->sdata->vif.type == NL80211_IFTYPE_STATION) { |
730 | /* Update last_rx only for unicast frames in order to prevent | 730 | /* Update last_rx only for unicast frames in order to prevent |
731 | * the Probe Request frames (the only broadcast frames from a | 731 | * the Probe Request frames (the only broadcast frames from a |
732 | * STA in infrastructure mode) from keeping a connection alive. | 732 | * STA in infrastructure mode) from keeping a connection alive. |
@@ -746,16 +746,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
746 | sta->last_noise = rx->status->noise; | 746 | sta->last_noise = rx->status->noise; |
747 | 747 | ||
748 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 748 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
749 | (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP || | 749 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
750 | rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) { | 750 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
751 | /* Change STA power saving mode only in the end of a frame | 751 | /* Change STA power saving mode only in the end of a frame |
752 | * exchange sequence */ | 752 | * exchange sequence */ |
753 | if (test_sta_flags(sta, WLAN_STA_PS) && | 753 | if (test_sta_flags(sta, WLAN_STA_PS) && |
754 | !ieee80211_has_pm(hdr->frame_control)) | 754 | !ieee80211_has_pm(hdr->frame_control)) |
755 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 755 | rx->sent_ps_buffered += ap_sta_ps_end(sta); |
756 | else if (!test_sta_flags(sta, WLAN_STA_PS) && | 756 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
757 | ieee80211_has_pm(hdr->frame_control)) | 757 | ieee80211_has_pm(hdr->frame_control)) |
758 | ap_sta_ps_start(dev, sta); | 758 | ap_sta_ps_start(sta); |
759 | } | 759 | } |
760 | 760 | ||
761 | /* Drop data::nullfunc frames silently, since they are used only to | 761 | /* Drop data::nullfunc frames silently, since they are used only to |
@@ -816,7 +816,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | |||
816 | 816 | ||
817 | static inline struct ieee80211_fragment_entry * | 817 | static inline struct ieee80211_fragment_entry * |
818 | ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | 818 | ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, |
819 | u16 fc, unsigned int frag, unsigned int seq, | 819 | unsigned int frag, unsigned int seq, |
820 | int rx_queue, struct ieee80211_hdr *hdr) | 820 | int rx_queue, struct ieee80211_hdr *hdr) |
821 | { | 821 | { |
822 | struct ieee80211_fragment_entry *entry; | 822 | struct ieee80211_fragment_entry *entry; |
@@ -825,7 +825,6 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | |||
825 | idx = sdata->fragment_next; | 825 | idx = sdata->fragment_next; |
826 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { | 826 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { |
827 | struct ieee80211_hdr *f_hdr; | 827 | struct ieee80211_hdr *f_hdr; |
828 | u16 f_fc; | ||
829 | 828 | ||
830 | idx--; | 829 | idx--; |
831 | if (idx < 0) | 830 | if (idx < 0) |
@@ -837,10 +836,13 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | |||
837 | entry->last_frag + 1 != frag) | 836 | entry->last_frag + 1 != frag) |
838 | continue; | 837 | continue; |
839 | 838 | ||
840 | f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data; | 839 | f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; |
841 | f_fc = le16_to_cpu(f_hdr->frame_control); | ||
842 | 840 | ||
843 | if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) || | 841 | /* |
842 | * Check ftype and addresses are equal, else check next fragment | ||
843 | */ | ||
844 | if (((hdr->frame_control ^ f_hdr->frame_control) & | ||
845 | cpu_to_le16(IEEE80211_FCTL_FTYPE)) || | ||
844 | compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || | 846 | compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || |
845 | compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) | 847 | compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) |
846 | continue; | 848 | continue; |
@@ -860,16 +862,18 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
860 | { | 862 | { |
861 | struct ieee80211_hdr *hdr; | 863 | struct ieee80211_hdr *hdr; |
862 | u16 sc; | 864 | u16 sc; |
865 | __le16 fc; | ||
863 | unsigned int frag, seq; | 866 | unsigned int frag, seq; |
864 | struct ieee80211_fragment_entry *entry; | 867 | struct ieee80211_fragment_entry *entry; |
865 | struct sk_buff *skb; | 868 | struct sk_buff *skb; |
866 | DECLARE_MAC_BUF(mac); | 869 | DECLARE_MAC_BUF(mac); |
867 | 870 | ||
868 | hdr = (struct ieee80211_hdr *) rx->skb->data; | 871 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
872 | fc = hdr->frame_control; | ||
869 | sc = le16_to_cpu(hdr->seq_ctrl); | 873 | sc = le16_to_cpu(hdr->seq_ctrl); |
870 | frag = sc & IEEE80211_SCTL_FRAG; | 874 | frag = sc & IEEE80211_SCTL_FRAG; |
871 | 875 | ||
872 | if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) || | 876 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
873 | (rx->skb)->len < 24 || | 877 | (rx->skb)->len < 24 || |
874 | is_multicast_ether_addr(hdr->addr1))) { | 878 | is_multicast_ether_addr(hdr->addr1))) { |
875 | /* not fragmented */ | 879 | /* not fragmented */ |
@@ -884,7 +888,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
884 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 888 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
885 | rx->queue, &(rx->skb)); | 889 | rx->queue, &(rx->skb)); |
886 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 890 | if (rx->key && rx->key->conf.alg == ALG_CCMP && |
887 | (rx->fc & IEEE80211_FCTL_PROTECTED)) { | 891 | ieee80211_has_protected(fc)) { |
888 | /* Store CCMP PN so that we can verify that the next | 892 | /* Store CCMP PN so that we can verify that the next |
889 | * fragment has a sequential PN value. */ | 893 | * fragment has a sequential PN value. */ |
890 | entry->ccmp = 1; | 894 | entry->ccmp = 1; |
@@ -898,8 +902,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
898 | /* This is a fragment for a frame that should already be pending in | 902 | /* This is a fragment for a frame that should already be pending in |
899 | * fragment cache. Add this fragment to the end of the pending entry. | 903 | * fragment cache. Add this fragment to the end of the pending entry. |
900 | */ | 904 | */ |
901 | entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq, | 905 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); |
902 | rx->queue, hdr); | ||
903 | if (!entry) { | 906 | if (!entry) { |
904 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 907 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
905 | return RX_DROP_MONITOR; | 908 | return RX_DROP_MONITOR; |
@@ -924,11 +927,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
924 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); | 927 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); |
925 | } | 928 | } |
926 | 929 | ||
927 | skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc)); | 930 | skb_pull(rx->skb, ieee80211_hdrlen(fc)); |
928 | __skb_queue_tail(&entry->skb_list, rx->skb); | 931 | __skb_queue_tail(&entry->skb_list, rx->skb); |
929 | entry->last_frag = frag; | 932 | entry->last_frag = frag; |
930 | entry->extra_len += rx->skb->len; | 933 | entry->extra_len += rx->skb->len; |
931 | if (rx->fc & IEEE80211_FCTL_MOREFRAGS) { | 934 | if (ieee80211_has_morefrags(fc)) { |
932 | rx->skb = NULL; | 935 | rx->skb = NULL; |
933 | return RX_QUEUED; | 936 | return RX_QUEUED; |
934 | } | 937 | } |
@@ -968,15 +971,14 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
968 | struct sk_buff *skb; | 971 | struct sk_buff *skb; |
969 | int no_pending_pkts; | 972 | int no_pending_pkts; |
970 | DECLARE_MAC_BUF(mac); | 973 | DECLARE_MAC_BUF(mac); |
974 | __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; | ||
971 | 975 | ||
972 | if (likely(!rx->sta || | 976 | if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || |
973 | (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL || | ||
974 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL || | ||
975 | !(rx->flags & IEEE80211_RX_RA_MATCH))) | 977 | !(rx->flags & IEEE80211_RX_RA_MATCH))) |
976 | return RX_CONTINUE; | 978 | return RX_CONTINUE; |
977 | 979 | ||
978 | if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) && | 980 | if ((sdata->vif.type != NL80211_IFTYPE_AP) && |
979 | (sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) | 981 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
980 | return RX_DROP_UNUSABLE; | 982 | return RX_DROP_UNUSABLE; |
981 | 983 | ||
982 | skb = skb_dequeue(&rx->sta->tx_filtered); | 984 | skb = skb_dequeue(&rx->sta->tx_filtered); |
@@ -1000,7 +1002,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1000 | 1002 | ||
1001 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1003 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1002 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", | 1004 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", |
1003 | print_mac(mac, rx->sta->addr), rx->sta->aid, | 1005 | print_mac(mac, rx->sta->sta.addr), rx->sta->sta.aid, |
1004 | skb_queue_len(&rx->sta->ps_tx_buf)); | 1006 | skb_queue_len(&rx->sta->ps_tx_buf)); |
1005 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1007 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1006 | 1008 | ||
@@ -1025,7 +1027,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1025 | */ | 1027 | */ |
1026 | printk(KERN_DEBUG "%s: STA %s sent PS Poll even " | 1028 | printk(KERN_DEBUG "%s: STA %s sent PS Poll even " |
1027 | "though there are no buffered frames for it\n", | 1029 | "though there are no buffered frames for it\n", |
1028 | rx->dev->name, print_mac(mac, rx->sta->addr)); | 1030 | rx->dev->name, print_mac(mac, rx->sta->sta.addr)); |
1029 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1031 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1030 | } | 1032 | } |
1031 | 1033 | ||
@@ -1050,7 +1052,6 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | |||
1050 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); | 1052 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); |
1051 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); | 1053 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); |
1052 | /* change frame type to non QOS */ | 1054 | /* change frame type to non QOS */ |
1053 | rx->fc &= ~IEEE80211_STYPE_QOS_DATA; | ||
1054 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 1055 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1055 | 1056 | ||
1056 | return RX_CONTINUE; | 1057 | return RX_CONTINUE; |
@@ -1067,7 +1068,7 @@ ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | |||
1067 | } | 1068 | } |
1068 | 1069 | ||
1069 | static int | 1070 | static int |
1070 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) | 1071 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) |
1071 | { | 1072 | { |
1072 | /* | 1073 | /* |
1073 | * Pass through unencrypted frames if the hardware has | 1074 | * Pass through unencrypted frames if the hardware has |
@@ -1077,9 +1078,8 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) | |||
1077 | return 0; | 1078 | return 0; |
1078 | 1079 | ||
1079 | /* Drop unencrypted frames if key is set. */ | 1080 | /* Drop unencrypted frames if key is set. */ |
1080 | if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && | 1081 | if (unlikely(!ieee80211_has_protected(fc) && |
1081 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 1082 | !ieee80211_is_nullfunc(fc) && |
1082 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && | ||
1083 | (rx->key || rx->sdata->drop_unencrypted))) | 1083 | (rx->key || rx->sdata->drop_unencrypted))) |
1084 | return -EACCES; | 1084 | return -EACCES; |
1085 | 1085 | ||
@@ -1091,7 +1091,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1091 | { | 1091 | { |
1092 | struct net_device *dev = rx->dev; | 1092 | struct net_device *dev = rx->dev; |
1093 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 1093 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
1094 | u16 fc, hdrlen, ethertype; | 1094 | u16 hdrlen, ethertype; |
1095 | u8 *payload; | 1095 | u8 *payload; |
1096 | u8 dst[ETH_ALEN]; | 1096 | u8 dst[ETH_ALEN]; |
1097 | u8 src[ETH_ALEN] __aligned(2); | 1097 | u8 src[ETH_ALEN] __aligned(2); |
@@ -1102,16 +1102,10 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1102 | DECLARE_MAC_BUF(mac3); | 1102 | DECLARE_MAC_BUF(mac3); |
1103 | DECLARE_MAC_BUF(mac4); | 1103 | DECLARE_MAC_BUF(mac4); |
1104 | 1104 | ||
1105 | fc = rx->fc; | 1105 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1106 | |||
1107 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | ||
1108 | return -1; | 1106 | return -1; |
1109 | 1107 | ||
1110 | hdrlen = ieee80211_get_hdrlen(fc); | 1108 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1111 | |||
1112 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1113 | hdrlen += ieee80211_get_mesh_hdrlen( | ||
1114 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); | ||
1115 | 1109 | ||
1116 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1110 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1117 | * header | 1111 | * header |
@@ -1122,42 +1116,38 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1122 | * 1 0 BSSID SA DA n/a | 1116 | * 1 0 BSSID SA DA n/a |
1123 | * 1 1 RA TA DA SA | 1117 | * 1 1 RA TA DA SA |
1124 | */ | 1118 | */ |
1125 | 1119 | memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); | |
1126 | switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 1120 | memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); |
1127 | case IEEE80211_FCTL_TODS: | 1121 | |
1128 | /* BSSID SA DA */ | 1122 | switch (hdr->frame_control & |
1129 | memcpy(dst, hdr->addr3, ETH_ALEN); | 1123 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
1130 | memcpy(src, hdr->addr2, ETH_ALEN); | 1124 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): |
1131 | 1125 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && | |
1132 | if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP && | 1126 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
1133 | sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) | ||
1134 | return -1; | 1127 | return -1; |
1135 | break; | 1128 | break; |
1136 | case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 1129 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
1137 | /* RA TA DA SA */ | 1130 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1138 | memcpy(dst, hdr->addr3, ETH_ALEN); | 1131 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1139 | memcpy(src, hdr->addr4, ETH_ALEN); | ||
1140 | |||
1141 | if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && | ||
1142 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) | ||
1143 | return -1; | 1132 | return -1; |
1133 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1134 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | ||
1135 | (skb->data + hdrlen); | ||
1136 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
1137 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | ||
1138 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | ||
1139 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | ||
1140 | } | ||
1141 | } | ||
1144 | break; | 1142 | break; |
1145 | case IEEE80211_FCTL_FROMDS: | 1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1146 | /* DA BSSID SA */ | 1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
1147 | memcpy(dst, hdr->addr1, ETH_ALEN); | ||
1148 | memcpy(src, hdr->addr3, ETH_ALEN); | ||
1149 | |||
1150 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA || | ||
1151 | (is_multicast_ether_addr(dst) && | 1145 | (is_multicast_ether_addr(dst) && |
1152 | !compare_ether_addr(src, dev->dev_addr))) | 1146 | !compare_ether_addr(src, dev->dev_addr))) |
1153 | return -1; | 1147 | return -1; |
1154 | break; | 1148 | break; |
1155 | case 0: | 1149 | case __constant_cpu_to_le16(0): |
1156 | /* DA SA BSSID */ | 1150 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1157 | memcpy(dst, hdr->addr1, ETH_ALEN); | ||
1158 | memcpy(src, hdr->addr2, ETH_ALEN); | ||
1159 | |||
1160 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | ||
1161 | return -1; | 1151 | return -1; |
1162 | break; | 1152 | break; |
1163 | } | 1153 | } |
@@ -1193,7 +1183,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1193 | /* | 1183 | /* |
1194 | * requires that rx->skb is a frame with ethernet header | 1184 | * requires that rx->skb is a frame with ethernet header |
1195 | */ | 1185 | */ |
1196 | static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) | 1186 | static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) |
1197 | { | 1187 | { |
1198 | static const u8 pae_group_addr[ETH_ALEN] __aligned(2) | 1188 | static const u8 pae_group_addr[ETH_ALEN] __aligned(2) |
1199 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; | 1189 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; |
@@ -1209,7 +1199,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) | |||
1209 | return true; | 1199 | return true; |
1210 | 1200 | ||
1211 | if (ieee80211_802_1x_port_control(rx) || | 1201 | if (ieee80211_802_1x_port_control(rx) || |
1212 | ieee80211_drop_unencrypted(rx)) | 1202 | ieee80211_drop_unencrypted(rx, fc)) |
1213 | return false; | 1203 | return false; |
1214 | 1204 | ||
1215 | return true; | 1205 | return true; |
@@ -1231,8 +1221,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1231 | skb = rx->skb; | 1221 | skb = rx->skb; |
1232 | xmit_skb = NULL; | 1222 | xmit_skb = NULL; |
1233 | 1223 | ||
1234 | if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP || | 1224 | if ((sdata->vif.type == NL80211_IFTYPE_AP || |
1235 | sdata->vif.type == IEEE80211_IF_TYPE_VLAN) && | 1225 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1226 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && | ||
1236 | (rx->flags & IEEE80211_RX_RA_MATCH)) { | 1227 | (rx->flags & IEEE80211_RX_RA_MATCH)) { |
1237 | if (is_multicast_ether_addr(ehdr->h_dest)) { | 1228 | if (is_multicast_ether_addr(ehdr->h_dest)) { |
1238 | /* | 1229 | /* |
@@ -1279,20 +1270,21 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1279 | { | 1270 | { |
1280 | struct net_device *dev = rx->dev; | 1271 | struct net_device *dev = rx->dev; |
1281 | struct ieee80211_local *local = rx->local; | 1272 | struct ieee80211_local *local = rx->local; |
1282 | u16 fc, ethertype; | 1273 | u16 ethertype; |
1283 | u8 *payload; | 1274 | u8 *payload; |
1284 | struct sk_buff *skb = rx->skb, *frame = NULL; | 1275 | struct sk_buff *skb = rx->skb, *frame = NULL; |
1276 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1277 | __le16 fc = hdr->frame_control; | ||
1285 | const struct ethhdr *eth; | 1278 | const struct ethhdr *eth; |
1286 | int remaining, err; | 1279 | int remaining, err; |
1287 | u8 dst[ETH_ALEN]; | 1280 | u8 dst[ETH_ALEN]; |
1288 | u8 src[ETH_ALEN]; | 1281 | u8 src[ETH_ALEN]; |
1289 | DECLARE_MAC_BUF(mac); | 1282 | DECLARE_MAC_BUF(mac); |
1290 | 1283 | ||
1291 | fc = rx->fc; | 1284 | if (unlikely(!ieee80211_is_data(fc))) |
1292 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) | ||
1293 | return RX_CONTINUE; | 1285 | return RX_CONTINUE; |
1294 | 1286 | ||
1295 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | 1287 | if (unlikely(!ieee80211_is_data_present(fc))) |
1296 | return RX_DROP_MONITOR; | 1288 | return RX_DROP_MONITOR; |
1297 | 1289 | ||
1298 | if (!(rx->flags & IEEE80211_RX_AMSDU)) | 1290 | if (!(rx->flags & IEEE80211_RX_AMSDU)) |
@@ -1374,7 +1366,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1374 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | 1366 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); |
1375 | } | 1367 | } |
1376 | 1368 | ||
1377 | if (!ieee80211_frame_allowed(rx)) { | 1369 | if (!ieee80211_frame_allowed(rx, fc)) { |
1378 | if (skb == frame) /* last frame */ | 1370 | if (skb == frame) /* last frame */ |
1379 | return RX_DROP_UNUSABLE; | 1371 | return RX_DROP_UNUSABLE; |
1380 | dev_kfree_skb(frame); | 1372 | dev_kfree_skb(frame); |
@@ -1387,7 +1379,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1387 | return RX_QUEUED; | 1379 | return RX_QUEUED; |
1388 | } | 1380 | } |
1389 | 1381 | ||
1390 | static ieee80211_rx_result debug_noinline | 1382 | #ifdef CONFIG_MAC80211_MESH |
1383 | static ieee80211_rx_result | ||
1391 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | 1384 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1392 | { | 1385 | { |
1393 | struct ieee80211_hdr *hdr; | 1386 | struct ieee80211_hdr *hdr; |
@@ -1406,6 +1399,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1406 | /* illegal frame */ | 1399 | /* illegal frame */ |
1407 | return RX_DROP_MONITOR; | 1400 | return RX_DROP_MONITOR; |
1408 | 1401 | ||
1402 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | ||
1403 | struct ieee80211_sub_if_data *sdata; | ||
1404 | struct mesh_path *mppath; | ||
1405 | |||
1406 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1407 | rcu_read_lock(); | ||
1408 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | ||
1409 | if (!mppath) { | ||
1410 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); | ||
1411 | } else { | ||
1412 | spin_lock_bh(&mppath->state_lock); | ||
1413 | mppath->exp_time = jiffies; | ||
1414 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) | ||
1415 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); | ||
1416 | spin_unlock_bh(&mppath->state_lock); | ||
1417 | } | ||
1418 | rcu_read_unlock(); | ||
1419 | } | ||
1420 | |||
1409 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1421 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) |
1410 | return RX_CONTINUE; | 1422 | return RX_CONTINUE; |
1411 | 1423 | ||
@@ -1413,7 +1425,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1413 | 1425 | ||
1414 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | 1426 | if (rx->flags & IEEE80211_RX_RA_MATCH) { |
1415 | if (!mesh_hdr->ttl) | 1427 | if (!mesh_hdr->ttl) |
1416 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, | 1428 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, |
1417 | dropped_frames_ttl); | 1429 | dropped_frames_ttl); |
1418 | else { | 1430 | else { |
1419 | struct ieee80211_hdr *fwd_hdr; | 1431 | struct ieee80211_hdr *fwd_hdr; |
@@ -1442,27 +1454,27 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1442 | else | 1454 | else |
1443 | return RX_DROP_MONITOR; | 1455 | return RX_DROP_MONITOR; |
1444 | } | 1456 | } |
1445 | 1457 | #endif | |
1446 | 1458 | ||
1447 | static ieee80211_rx_result debug_noinline | 1459 | static ieee80211_rx_result debug_noinline |
1448 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1460 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1449 | { | 1461 | { |
1450 | struct net_device *dev = rx->dev; | 1462 | struct net_device *dev = rx->dev; |
1451 | u16 fc; | 1463 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1464 | __le16 fc = hdr->frame_control; | ||
1452 | int err; | 1465 | int err; |
1453 | 1466 | ||
1454 | fc = rx->fc; | 1467 | if (unlikely(!ieee80211_is_data(hdr->frame_control))) |
1455 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) | ||
1456 | return RX_CONTINUE; | 1468 | return RX_CONTINUE; |
1457 | 1469 | ||
1458 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | 1470 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1459 | return RX_DROP_MONITOR; | 1471 | return RX_DROP_MONITOR; |
1460 | 1472 | ||
1461 | err = ieee80211_data_to_8023(rx); | 1473 | err = ieee80211_data_to_8023(rx); |
1462 | if (unlikely(err)) | 1474 | if (unlikely(err)) |
1463 | return RX_DROP_UNUSABLE; | 1475 | return RX_DROP_UNUSABLE; |
1464 | 1476 | ||
1465 | if (!ieee80211_frame_allowed(rx)) | 1477 | if (!ieee80211_frame_allowed(rx, fc)) |
1466 | return RX_DROP_MONITOR; | 1478 | return RX_DROP_MONITOR; |
1467 | 1479 | ||
1468 | rx->skb->dev = dev; | 1480 | rx->skb->dev = dev; |
@@ -1520,22 +1532,97 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1520 | } | 1532 | } |
1521 | 1533 | ||
1522 | static ieee80211_rx_result debug_noinline | 1534 | static ieee80211_rx_result debug_noinline |
1535 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | ||
1536 | { | ||
1537 | struct ieee80211_local *local = rx->local; | ||
1538 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1539 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1540 | int len = rx->skb->len; | ||
1541 | |||
1542 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
1543 | return RX_CONTINUE; | ||
1544 | |||
1545 | if (!rx->sta) | ||
1546 | return RX_DROP_MONITOR; | ||
1547 | |||
1548 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
1549 | return RX_DROP_MONITOR; | ||
1550 | |||
1551 | /* all categories we currently handle have action_code */ | ||
1552 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1553 | return RX_DROP_MONITOR; | ||
1554 | |||
1555 | /* | ||
1556 | * FIXME: revisit this, I'm sure we should handle most | ||
1557 | * of these frames in other modes as well! | ||
1558 | */ | ||
1559 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
1560 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
1561 | return RX_CONTINUE; | ||
1562 | |||
1563 | switch (mgmt->u.action.category) { | ||
1564 | case WLAN_CATEGORY_BACK: | ||
1565 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
1566 | case WLAN_ACTION_ADDBA_REQ: | ||
1567 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1568 | sizeof(mgmt->u.action.u.addba_req))) | ||
1569 | return RX_DROP_MONITOR; | ||
1570 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | ||
1571 | break; | ||
1572 | case WLAN_ACTION_ADDBA_RESP: | ||
1573 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1574 | sizeof(mgmt->u.action.u.addba_resp))) | ||
1575 | return RX_DROP_MONITOR; | ||
1576 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | ||
1577 | break; | ||
1578 | case WLAN_ACTION_DELBA: | ||
1579 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1580 | sizeof(mgmt->u.action.u.delba))) | ||
1581 | return RX_DROP_MONITOR; | ||
1582 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | ||
1583 | break; | ||
1584 | } | ||
1585 | break; | ||
1586 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
1587 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | ||
1588 | return RX_DROP_MONITOR; | ||
1589 | switch (mgmt->u.action.u.measurement.action_code) { | ||
1590 | case WLAN_ACTION_SPCT_MSR_REQ: | ||
1591 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1592 | sizeof(mgmt->u.action.u.measurement))) | ||
1593 | return RX_DROP_MONITOR; | ||
1594 | ieee80211_process_measurement_req(sdata, mgmt, len); | ||
1595 | break; | ||
1596 | } | ||
1597 | break; | ||
1598 | default: | ||
1599 | return RX_CONTINUE; | ||
1600 | } | ||
1601 | |||
1602 | rx->sta->rx_packets++; | ||
1603 | dev_kfree_skb(rx->skb); | ||
1604 | return RX_QUEUED; | ||
1605 | } | ||
1606 | |||
1607 | static ieee80211_rx_result debug_noinline | ||
1523 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1608 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1524 | { | 1609 | { |
1525 | struct ieee80211_sub_if_data *sdata; | 1610 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1526 | 1611 | ||
1527 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1612 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1528 | return RX_DROP_MONITOR; | 1613 | return RX_DROP_MONITOR; |
1529 | 1614 | ||
1530 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1615 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1531 | if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1616 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); |
1532 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS || | 1617 | |
1533 | sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) && | 1618 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1534 | !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) | 1619 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1535 | ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status); | ||
1536 | else | ||
1537 | return RX_DROP_MONITOR; | 1620 | return RX_DROP_MONITOR; |
1538 | 1621 | ||
1622 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) | ||
1623 | return RX_DROP_MONITOR; | ||
1624 | |||
1625 | ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); | ||
1539 | return RX_QUEUED; | 1626 | return RX_QUEUED; |
1540 | } | 1627 | } |
1541 | 1628 | ||
@@ -1565,7 +1652,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1565 | if (!ieee80211_has_protected(hdr->frame_control)) | 1652 | if (!ieee80211_has_protected(hdr->frame_control)) |
1566 | goto ignore; | 1653 | goto ignore; |
1567 | 1654 | ||
1568 | if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) { | 1655 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { |
1569 | /* | 1656 | /* |
1570 | * APs with pairwise keys should never receive Michael MIC | 1657 | * APs with pairwise keys should never receive Michael MIC |
1571 | * errors for non-zero keyidx because these are reserved for | 1658 | * errors for non-zero keyidx because these are reserved for |
@@ -1579,7 +1666,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1579 | !ieee80211_is_auth(hdr->frame_control)) | 1666 | !ieee80211_is_auth(hdr->frame_control)) |
1580 | goto ignore; | 1667 | goto ignore; |
1581 | 1668 | ||
1582 | mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); | 1669 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); |
1583 | ignore: | 1670 | ignore: |
1584 | dev_kfree_skb(rx->skb); | 1671 | dev_kfree_skb(rx->skb); |
1585 | rx->skb = NULL; | 1672 | rx->skb = NULL; |
@@ -1635,7 +1722,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | |||
1635 | if (!netif_running(sdata->dev)) | 1722 | if (!netif_running(sdata->dev)) |
1636 | continue; | 1723 | continue; |
1637 | 1724 | ||
1638 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || | 1725 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || |
1639 | !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | 1726 | !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) |
1640 | continue; | 1727 | continue; |
1641 | 1728 | ||
@@ -1694,10 +1781,13 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1694 | /* must be after MMIC verify so header is counted in MPDU mic */ | 1781 | /* must be after MMIC verify so header is counted in MPDU mic */ |
1695 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | 1782 | CALL_RXH(ieee80211_rx_h_remove_qos_control) |
1696 | CALL_RXH(ieee80211_rx_h_amsdu) | 1783 | CALL_RXH(ieee80211_rx_h_amsdu) |
1784 | #ifdef CONFIG_MAC80211_MESH | ||
1697 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1785 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1698 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 1786 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
1787 | #endif | ||
1699 | CALL_RXH(ieee80211_rx_h_data) | 1788 | CALL_RXH(ieee80211_rx_h_data) |
1700 | CALL_RXH(ieee80211_rx_h_ctrl) | 1789 | CALL_RXH(ieee80211_rx_h_ctrl) |
1790 | CALL_RXH(ieee80211_rx_h_action) | ||
1701 | CALL_RXH(ieee80211_rx_h_mgmt) | 1791 | CALL_RXH(ieee80211_rx_h_mgmt) |
1702 | 1792 | ||
1703 | #undef CALL_RXH | 1793 | #undef CALL_RXH |
@@ -1733,7 +1823,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1733 | int multicast = is_multicast_ether_addr(hdr->addr1); | 1823 | int multicast = is_multicast_ether_addr(hdr->addr1); |
1734 | 1824 | ||
1735 | switch (sdata->vif.type) { | 1825 | switch (sdata->vif.type) { |
1736 | case IEEE80211_IF_TYPE_STA: | 1826 | case NL80211_IFTYPE_STATION: |
1737 | if (!bssid) | 1827 | if (!bssid) |
1738 | return 0; | 1828 | return 0; |
1739 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1829 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
@@ -1748,14 +1838,10 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1748 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1838 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1749 | } | 1839 | } |
1750 | break; | 1840 | break; |
1751 | case IEEE80211_IF_TYPE_IBSS: | 1841 | case NL80211_IFTYPE_ADHOC: |
1752 | if (!bssid) | 1842 | if (!bssid) |
1753 | return 0; | 1843 | return 0; |
1754 | if (ieee80211_is_beacon(hdr->frame_control)) { | 1844 | if (ieee80211_is_beacon(hdr->frame_control)) { |
1755 | if (!rx->sta) | ||
1756 | rx->sta = ieee80211_ibss_add_sta(sdata->dev, | ||
1757 | rx->skb, bssid, hdr->addr2, | ||
1758 | BIT(rx->status->rate_idx)); | ||
1759 | return 1; | 1845 | return 1; |
1760 | } | 1846 | } |
1761 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1847 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
@@ -1769,11 +1855,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1769 | return 0; | 1855 | return 0; |
1770 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1856 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1771 | } else if (!rx->sta) | 1857 | } else if (!rx->sta) |
1772 | rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, | 1858 | rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb, |
1773 | bssid, hdr->addr2, | 1859 | bssid, hdr->addr2, |
1774 | BIT(rx->status->rate_idx)); | 1860 | BIT(rx->status->rate_idx)); |
1775 | break; | 1861 | break; |
1776 | case IEEE80211_IF_TYPE_MESH_POINT: | 1862 | case NL80211_IFTYPE_MESH_POINT: |
1777 | if (!multicast && | 1863 | if (!multicast && |
1778 | compare_ether_addr(sdata->dev->dev_addr, | 1864 | compare_ether_addr(sdata->dev->dev_addr, |
1779 | hdr->addr1) != 0) { | 1865 | hdr->addr1) != 0) { |
@@ -1783,8 +1869,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1783 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1869 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1784 | } | 1870 | } |
1785 | break; | 1871 | break; |
1786 | case IEEE80211_IF_TYPE_VLAN: | 1872 | case NL80211_IFTYPE_AP_VLAN: |
1787 | case IEEE80211_IF_TYPE_AP: | 1873 | case NL80211_IFTYPE_AP: |
1788 | if (!bssid) { | 1874 | if (!bssid) { |
1789 | if (compare_ether_addr(sdata->dev->dev_addr, | 1875 | if (compare_ether_addr(sdata->dev->dev_addr, |
1790 | hdr->addr1)) | 1876 | hdr->addr1)) |
@@ -1796,16 +1882,17 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1796 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1882 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1797 | } | 1883 | } |
1798 | break; | 1884 | break; |
1799 | case IEEE80211_IF_TYPE_WDS: | 1885 | case NL80211_IFTYPE_WDS: |
1800 | if (bssid || !ieee80211_is_data(hdr->frame_control)) | 1886 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
1801 | return 0; | 1887 | return 0; |
1802 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 1888 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
1803 | return 0; | 1889 | return 0; |
1804 | break; | 1890 | break; |
1805 | case IEEE80211_IF_TYPE_MNTR: | 1891 | case NL80211_IFTYPE_MONITOR: |
1806 | /* take everything */ | 1892 | /* take everything */ |
1807 | break; | 1893 | break; |
1808 | case IEEE80211_IF_TYPE_INVALID: | 1894 | case NL80211_IFTYPE_UNSPECIFIED: |
1895 | case __NL80211_IFTYPE_AFTER_LAST: | ||
1809 | /* should never get here */ | 1896 | /* should never get here */ |
1810 | WARN_ON(1); | 1897 | WARN_ON(1); |
1811 | break; | 1898 | break; |
@@ -1827,23 +1914,20 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1827 | struct ieee80211_sub_if_data *sdata; | 1914 | struct ieee80211_sub_if_data *sdata; |
1828 | struct ieee80211_hdr *hdr; | 1915 | struct ieee80211_hdr *hdr; |
1829 | struct ieee80211_rx_data rx; | 1916 | struct ieee80211_rx_data rx; |
1830 | u16 type; | ||
1831 | int prepares; | 1917 | int prepares; |
1832 | struct ieee80211_sub_if_data *prev = NULL; | 1918 | struct ieee80211_sub_if_data *prev = NULL; |
1833 | struct sk_buff *skb_new; | 1919 | struct sk_buff *skb_new; |
1834 | u8 *bssid; | 1920 | u8 *bssid; |
1835 | 1921 | ||
1836 | hdr = (struct ieee80211_hdr *) skb->data; | 1922 | hdr = (struct ieee80211_hdr *)skb->data; |
1837 | memset(&rx, 0, sizeof(rx)); | 1923 | memset(&rx, 0, sizeof(rx)); |
1838 | rx.skb = skb; | 1924 | rx.skb = skb; |
1839 | rx.local = local; | 1925 | rx.local = local; |
1840 | 1926 | ||
1841 | rx.status = status; | 1927 | rx.status = status; |
1842 | rx.rate = rate; | 1928 | rx.rate = rate; |
1843 | rx.fc = le16_to_cpu(hdr->frame_control); | ||
1844 | type = rx.fc & IEEE80211_FCTL_FTYPE; | ||
1845 | 1929 | ||
1846 | if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) | 1930 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) |
1847 | local->dot11ReceivedFragmentCount++; | 1931 | local->dot11ReceivedFragmentCount++; |
1848 | 1932 | ||
1849 | rx.sta = sta_info_get(local, hdr->addr2); | 1933 | rx.sta = sta_info_get(local, hdr->addr2); |
@@ -1857,7 +1941,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1857 | return; | 1941 | return; |
1858 | } | 1942 | } |
1859 | 1943 | ||
1860 | if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning)) | 1944 | if (unlikely(local->sw_scanning || local->hw_scanning)) |
1861 | rx.flags |= IEEE80211_RX_IN_SCAN; | 1945 | rx.flags |= IEEE80211_RX_IN_SCAN; |
1862 | 1946 | ||
1863 | ieee80211_parse_qos(&rx); | 1947 | ieee80211_parse_qos(&rx); |
@@ -1869,7 +1953,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1869 | if (!netif_running(sdata->dev)) | 1953 | if (!netif_running(sdata->dev)) |
1870 | continue; | 1954 | continue; |
1871 | 1955 | ||
1872 | if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) | 1956 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) |
1873 | continue; | 1957 | continue; |
1874 | 1958 | ||
1875 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); | 1959 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); |
@@ -1904,14 +1988,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1904 | prev->dev->name); | 1988 | prev->dev->name); |
1905 | continue; | 1989 | continue; |
1906 | } | 1990 | } |
1907 | rx.fc = le16_to_cpu(hdr->frame_control); | ||
1908 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); | 1991 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); |
1909 | prev = sdata; | 1992 | prev = sdata; |
1910 | } | 1993 | } |
1911 | if (prev) { | 1994 | if (prev) |
1912 | rx.fc = le16_to_cpu(hdr->frame_control); | ||
1913 | ieee80211_invoke_rx_handlers(prev, &rx, skb); | 1995 | ieee80211_invoke_rx_handlers(prev, &rx, skb); |
1914 | } else | 1996 | else |
1915 | dev_kfree_skb(skb); | 1997 | dev_kfree_skb(skb); |
1916 | } | 1998 | } |
1917 | 1999 | ||
@@ -2080,7 +2162,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2080 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 2162 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
2081 | sc = le16_to_cpu(hdr->seq_ctrl); | 2163 | sc = le16_to_cpu(hdr->seq_ctrl); |
2082 | if (sc & IEEE80211_SCTL_FRAG) { | 2164 | if (sc & IEEE80211_SCTL_FRAG) { |
2083 | ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, | 2165 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, |
2084 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 2166 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); |
2085 | ret = 1; | 2167 | ret = 1; |
2086 | goto end_reorder; | 2168 | goto end_reorder; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c new file mode 100644 index 000000000000..416bb41099f3 --- /dev/null +++ b/net/mac80211/scan.c | |||
@@ -0,0 +1,938 @@ | |||
1 | /* | ||
2 | * Scanning implementation | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* TODO: | ||
16 | * order BSS list by RSSI(?) ("quality of AP") | ||
17 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | ||
18 | * SSID) | ||
19 | */ | ||
20 | |||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/if_arp.h> | ||
23 | #include <net/mac80211.h> | ||
24 | #include <net/iw_handler.h> | ||
25 | |||
26 | #include "ieee80211_i.h" | ||
27 | #include "mesh.h" | ||
28 | |||
29 | #define IEEE80211_PROBE_DELAY (HZ / 33) | ||
30 | #define IEEE80211_CHANNEL_TIME (HZ / 33) | ||
31 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) | ||
32 | |||
33 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) | ||
34 | { | ||
35 | spin_lock_init(&local->bss_lock); | ||
36 | INIT_LIST_HEAD(&local->bss_list); | ||
37 | } | ||
38 | |||
39 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) | ||
40 | { | ||
41 | struct ieee80211_bss *bss, *tmp; | ||
42 | |||
43 | list_for_each_entry_safe(bss, tmp, &local->bss_list, list) | ||
44 | ieee80211_rx_bss_put(local, bss); | ||
45 | } | ||
46 | |||
47 | struct ieee80211_bss * | ||
48 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | ||
49 | u8 *ssid, u8 ssid_len) | ||
50 | { | ||
51 | struct ieee80211_bss *bss; | ||
52 | |||
53 | spin_lock_bh(&local->bss_lock); | ||
54 | bss = local->bss_hash[STA_HASH(bssid)]; | ||
55 | while (bss) { | ||
56 | if (!bss_mesh_cfg(bss) && | ||
57 | !memcmp(bss->bssid, bssid, ETH_ALEN) && | ||
58 | bss->freq == freq && | ||
59 | bss->ssid_len == ssid_len && | ||
60 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
61 | atomic_inc(&bss->users); | ||
62 | break; | ||
63 | } | ||
64 | bss = bss->hnext; | ||
65 | } | ||
66 | spin_unlock_bh(&local->bss_lock); | ||
67 | return bss; | ||
68 | } | ||
69 | |||
70 | /* Caller must hold local->bss_lock */ | ||
71 | static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, | ||
72 | struct ieee80211_bss *bss) | ||
73 | { | ||
74 | u8 hash_idx; | ||
75 | |||
76 | if (bss_mesh_cfg(bss)) | ||
77 | hash_idx = mesh_id_hash(bss_mesh_id(bss), | ||
78 | bss_mesh_id_len(bss)); | ||
79 | else | ||
80 | hash_idx = STA_HASH(bss->bssid); | ||
81 | |||
82 | bss->hnext = local->bss_hash[hash_idx]; | ||
83 | local->bss_hash[hash_idx] = bss; | ||
84 | } | ||
85 | |||
86 | /* Caller must hold local->bss_lock */ | ||
87 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, | ||
88 | struct ieee80211_bss *bss) | ||
89 | { | ||
90 | struct ieee80211_bss *b, *prev = NULL; | ||
91 | b = local->bss_hash[STA_HASH(bss->bssid)]; | ||
92 | while (b) { | ||
93 | if (b == bss) { | ||
94 | if (!prev) | ||
95 | local->bss_hash[STA_HASH(bss->bssid)] = | ||
96 | bss->hnext; | ||
97 | else | ||
98 | prev->hnext = bss->hnext; | ||
99 | break; | ||
100 | } | ||
101 | prev = b; | ||
102 | b = b->hnext; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | struct ieee80211_bss * | ||
107 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
108 | u8 *ssid, u8 ssid_len) | ||
109 | { | ||
110 | struct ieee80211_bss *bss; | ||
111 | |||
112 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
113 | if (!bss) | ||
114 | return NULL; | ||
115 | atomic_set(&bss->users, 2); | ||
116 | memcpy(bss->bssid, bssid, ETH_ALEN); | ||
117 | bss->freq = freq; | ||
118 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
119 | memcpy(bss->ssid, ssid, ssid_len); | ||
120 | bss->ssid_len = ssid_len; | ||
121 | } | ||
122 | |||
123 | spin_lock_bh(&local->bss_lock); | ||
124 | /* TODO: order by RSSI? */ | ||
125 | list_add_tail(&bss->list, &local->bss_list); | ||
126 | __ieee80211_rx_bss_hash_add(local, bss); | ||
127 | spin_unlock_bh(&local->bss_lock); | ||
128 | return bss; | ||
129 | } | ||
130 | |||
131 | #ifdef CONFIG_MAC80211_MESH | ||
132 | static struct ieee80211_bss * | ||
133 | ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, | ||
134 | u8 *mesh_cfg, int freq) | ||
135 | { | ||
136 | struct ieee80211_bss *bss; | ||
137 | |||
138 | spin_lock_bh(&local->bss_lock); | ||
139 | bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; | ||
140 | while (bss) { | ||
141 | if (bss_mesh_cfg(bss) && | ||
142 | !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && | ||
143 | bss->freq == freq && | ||
144 | mesh_id_len == bss->mesh_id_len && | ||
145 | (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, | ||
146 | mesh_id_len))) { | ||
147 | atomic_inc(&bss->users); | ||
148 | break; | ||
149 | } | ||
150 | bss = bss->hnext; | ||
151 | } | ||
152 | spin_unlock_bh(&local->bss_lock); | ||
153 | return bss; | ||
154 | } | ||
155 | |||
156 | static struct ieee80211_bss * | ||
157 | ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, | ||
158 | u8 *mesh_cfg, int mesh_config_len, int freq) | ||
159 | { | ||
160 | struct ieee80211_bss *bss; | ||
161 | |||
162 | if (mesh_config_len != MESH_CFG_LEN) | ||
163 | return NULL; | ||
164 | |||
165 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
166 | if (!bss) | ||
167 | return NULL; | ||
168 | |||
169 | bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); | ||
170 | if (!bss->mesh_cfg) { | ||
171 | kfree(bss); | ||
172 | return NULL; | ||
173 | } | ||
174 | |||
175 | if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { | ||
176 | bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); | ||
177 | if (!bss->mesh_id) { | ||
178 | kfree(bss->mesh_cfg); | ||
179 | kfree(bss); | ||
180 | return NULL; | ||
181 | } | ||
182 | memcpy(bss->mesh_id, mesh_id, mesh_id_len); | ||
183 | } | ||
184 | |||
185 | atomic_set(&bss->users, 2); | ||
186 | memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); | ||
187 | bss->mesh_id_len = mesh_id_len; | ||
188 | bss->freq = freq; | ||
189 | spin_lock_bh(&local->bss_lock); | ||
190 | /* TODO: order by RSSI? */ | ||
191 | list_add_tail(&bss->list, &local->bss_list); | ||
192 | __ieee80211_rx_bss_hash_add(local, bss); | ||
193 | spin_unlock_bh(&local->bss_lock); | ||
194 | return bss; | ||
195 | } | ||
196 | #endif | ||
197 | |||
198 | static void ieee80211_rx_bss_free(struct ieee80211_bss *bss) | ||
199 | { | ||
200 | kfree(bss->ies); | ||
201 | kfree(bss_mesh_id(bss)); | ||
202 | kfree(bss_mesh_cfg(bss)); | ||
203 | kfree(bss); | ||
204 | } | ||
205 | |||
206 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
207 | struct ieee80211_bss *bss) | ||
208 | { | ||
209 | local_bh_disable(); | ||
210 | if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) { | ||
211 | local_bh_enable(); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | __ieee80211_rx_bss_hash_del(local, bss); | ||
216 | list_del(&bss->list); | ||
217 | spin_unlock_bh(&local->bss_lock); | ||
218 | ieee80211_rx_bss_free(bss); | ||
219 | } | ||
220 | |||
221 | struct ieee80211_bss * | ||
222 | ieee80211_bss_info_update(struct ieee80211_local *local, | ||
223 | struct ieee80211_rx_status *rx_status, | ||
224 | struct ieee80211_mgmt *mgmt, | ||
225 | size_t len, | ||
226 | struct ieee802_11_elems *elems, | ||
227 | int freq, bool beacon) | ||
228 | { | ||
229 | struct ieee80211_bss *bss; | ||
230 | int clen; | ||
231 | |||
232 | #ifdef CONFIG_MAC80211_MESH | ||
233 | if (elems->mesh_config) | ||
234 | bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, | ||
235 | elems->mesh_id_len, elems->mesh_config, freq); | ||
236 | else | ||
237 | #endif | ||
238 | bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, | ||
239 | elems->ssid, elems->ssid_len); | ||
240 | if (!bss) { | ||
241 | #ifdef CONFIG_MAC80211_MESH | ||
242 | if (elems->mesh_config) | ||
243 | bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, | ||
244 | elems->mesh_id_len, elems->mesh_config, | ||
245 | elems->mesh_config_len, freq); | ||
246 | else | ||
247 | #endif | ||
248 | bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, | ||
249 | elems->ssid, elems->ssid_len); | ||
250 | if (!bss) | ||
251 | return NULL; | ||
252 | } else { | ||
253 | #if 0 | ||
254 | /* TODO: order by RSSI? */ | ||
255 | spin_lock_bh(&local->bss_lock); | ||
256 | list_move_tail(&bss->list, &local->bss_list); | ||
257 | spin_unlock_bh(&local->bss_lock); | ||
258 | #endif | ||
259 | } | ||
260 | |||
261 | /* save the ERP value so that it is available at association time */ | ||
262 | if (elems->erp_info && elems->erp_info_len >= 1) { | ||
263 | bss->erp_value = elems->erp_info[0]; | ||
264 | bss->has_erp_value = 1; | ||
265 | } | ||
266 | |||
267 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | ||
268 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | ||
269 | |||
270 | if (elems->tim) { | ||
271 | struct ieee80211_tim_ie *tim_ie = | ||
272 | (struct ieee80211_tim_ie *)elems->tim; | ||
273 | bss->dtim_period = tim_ie->dtim_period; | ||
274 | } | ||
275 | |||
276 | /* set default value for buggy APs */ | ||
277 | if (!elems->tim || bss->dtim_period == 0) | ||
278 | bss->dtim_period = 1; | ||
279 | |||
280 | bss->supp_rates_len = 0; | ||
281 | if (elems->supp_rates) { | ||
282 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
283 | if (clen > elems->supp_rates_len) | ||
284 | clen = elems->supp_rates_len; | ||
285 | memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, | ||
286 | clen); | ||
287 | bss->supp_rates_len += clen; | ||
288 | } | ||
289 | if (elems->ext_supp_rates) { | ||
290 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
291 | if (clen > elems->ext_supp_rates_len) | ||
292 | clen = elems->ext_supp_rates_len; | ||
293 | memcpy(&bss->supp_rates[bss->supp_rates_len], | ||
294 | elems->ext_supp_rates, clen); | ||
295 | bss->supp_rates_len += clen; | ||
296 | } | ||
297 | |||
298 | bss->band = rx_status->band; | ||
299 | |||
300 | bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); | ||
301 | bss->last_update = jiffies; | ||
302 | bss->signal = rx_status->signal; | ||
303 | bss->noise = rx_status->noise; | ||
304 | bss->qual = rx_status->qual; | ||
305 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | ||
306 | |||
307 | if (!beacon) | ||
308 | bss->last_probe_resp = jiffies; | ||
309 | |||
310 | /* | ||
311 | * For probe responses, or if we don't have any information yet, | ||
312 | * use the IEs from the beacon. | ||
313 | */ | ||
314 | if (!bss->ies || !beacon) { | ||
315 | if (bss->ies == NULL || bss->ies_len < elems->total_len) { | ||
316 | kfree(bss->ies); | ||
317 | bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); | ||
318 | } | ||
319 | if (bss->ies) { | ||
320 | memcpy(bss->ies, elems->ie_start, elems->total_len); | ||
321 | bss->ies_len = elems->total_len; | ||
322 | } else | ||
323 | bss->ies_len = 0; | ||
324 | } | ||
325 | |||
326 | return bss; | ||
327 | } | ||
328 | |||
329 | ieee80211_rx_result | ||
330 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
331 | struct ieee80211_rx_status *rx_status) | ||
332 | { | ||
333 | struct ieee80211_mgmt *mgmt; | ||
334 | struct ieee80211_bss *bss; | ||
335 | u8 *elements; | ||
336 | struct ieee80211_channel *channel; | ||
337 | size_t baselen; | ||
338 | int freq; | ||
339 | __le16 fc; | ||
340 | bool presp, beacon = false; | ||
341 | struct ieee802_11_elems elems; | ||
342 | |||
343 | if (skb->len < 2) | ||
344 | return RX_DROP_UNUSABLE; | ||
345 | |||
346 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
347 | fc = mgmt->frame_control; | ||
348 | |||
349 | if (ieee80211_is_ctl(fc)) | ||
350 | return RX_CONTINUE; | ||
351 | |||
352 | if (skb->len < 24) | ||
353 | return RX_DROP_MONITOR; | ||
354 | |||
355 | presp = ieee80211_is_probe_resp(fc); | ||
356 | if (presp) { | ||
357 | /* ignore ProbeResp to foreign address */ | ||
358 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | ||
359 | return RX_DROP_MONITOR; | ||
360 | |||
361 | presp = true; | ||
362 | elements = mgmt->u.probe_resp.variable; | ||
363 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | ||
364 | } else { | ||
365 | beacon = ieee80211_is_beacon(fc); | ||
366 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); | ||
367 | elements = mgmt->u.beacon.variable; | ||
368 | } | ||
369 | |||
370 | if (!presp && !beacon) | ||
371 | return RX_CONTINUE; | ||
372 | |||
373 | if (baselen > skb->len) | ||
374 | return RX_DROP_MONITOR; | ||
375 | |||
376 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | ||
377 | |||
378 | if (elems.ds_params && elems.ds_params_len == 1) | ||
379 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | ||
380 | else | ||
381 | freq = rx_status->freq; | ||
382 | |||
383 | channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); | ||
384 | |||
385 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
386 | return RX_DROP_MONITOR; | ||
387 | |||
388 | bss = ieee80211_bss_info_update(sdata->local, rx_status, | ||
389 | mgmt, skb->len, &elems, | ||
390 | freq, beacon); | ||
391 | if (bss) | ||
392 | ieee80211_rx_bss_put(sdata->local, bss); | ||
393 | |||
394 | dev_kfree_skb(skb); | ||
395 | return RX_QUEUED; | ||
396 | } | ||
397 | |||
398 | static void ieee80211_send_nullfunc(struct ieee80211_local *local, | ||
399 | struct ieee80211_sub_if_data *sdata, | ||
400 | int powersave) | ||
401 | { | ||
402 | struct sk_buff *skb; | ||
403 | struct ieee80211_hdr *nullfunc; | ||
404 | __le16 fc; | ||
405 | |||
406 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | ||
407 | if (!skb) { | ||
408 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | ||
409 | "frame\n", sdata->dev->name); | ||
410 | return; | ||
411 | } | ||
412 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
413 | |||
414 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
415 | memset(nullfunc, 0, 24); | ||
416 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | ||
417 | IEEE80211_FCTL_TODS); | ||
418 | if (powersave) | ||
419 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
420 | nullfunc->frame_control = fc; | ||
421 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); | ||
422 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | ||
423 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); | ||
424 | |||
425 | ieee80211_tx_skb(sdata, skb, 0); | ||
426 | } | ||
427 | |||
428 | void ieee80211_scan_completed(struct ieee80211_hw *hw) | ||
429 | { | ||
430 | struct ieee80211_local *local = hw_to_local(hw); | ||
431 | struct ieee80211_sub_if_data *sdata; | ||
432 | union iwreq_data wrqu; | ||
433 | |||
434 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) | ||
435 | return; | ||
436 | |||
437 | local->last_scan_completed = jiffies; | ||
438 | memset(&wrqu, 0, sizeof(wrqu)); | ||
439 | |||
440 | /* | ||
441 | * local->scan_sdata could have been NULLed by the interface | ||
442 | * down code in case we were scanning on an interface that is | ||
443 | * being taken down. | ||
444 | */ | ||
445 | sdata = local->scan_sdata; | ||
446 | if (sdata) | ||
447 | wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
448 | |||
449 | if (local->hw_scanning) { | ||
450 | local->hw_scanning = false; | ||
451 | if (ieee80211_hw_config(local)) | ||
452 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
453 | "channel after scan\n", wiphy_name(local->hw.wiphy)); | ||
454 | |||
455 | goto done; | ||
456 | } | ||
457 | |||
458 | local->sw_scanning = false; | ||
459 | if (ieee80211_hw_config(local)) | ||
460 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
461 | "channel after scan\n", wiphy_name(local->hw.wiphy)); | ||
462 | |||
463 | |||
464 | netif_tx_lock_bh(local->mdev); | ||
465 | netif_addr_lock(local->mdev); | ||
466 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | ||
467 | local->ops->configure_filter(local_to_hw(local), | ||
468 | FIF_BCN_PRBRESP_PROMISC, | ||
469 | &local->filter_flags, | ||
470 | local->mdev->mc_count, | ||
471 | local->mdev->mc_list); | ||
472 | |||
473 | netif_addr_unlock(local->mdev); | ||
474 | netif_tx_unlock_bh(local->mdev); | ||
475 | |||
476 | rcu_read_lock(); | ||
477 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
478 | /* Tell AP we're back */ | ||
479 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
480 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | ||
481 | ieee80211_send_nullfunc(local, sdata, 0); | ||
482 | netif_tx_wake_all_queues(sdata->dev); | ||
483 | } | ||
484 | } else | ||
485 | netif_tx_wake_all_queues(sdata->dev); | ||
486 | } | ||
487 | rcu_read_unlock(); | ||
488 | |||
489 | done: | ||
490 | ieee80211_mlme_notify_scan_completed(local); | ||
491 | ieee80211_mesh_notify_scan_completed(local); | ||
492 | } | ||
493 | EXPORT_SYMBOL(ieee80211_scan_completed); | ||
494 | |||
495 | |||
496 | void ieee80211_scan_work(struct work_struct *work) | ||
497 | { | ||
498 | struct ieee80211_local *local = | ||
499 | container_of(work, struct ieee80211_local, scan_work.work); | ||
500 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
501 | struct ieee80211_supported_band *sband; | ||
502 | struct ieee80211_channel *chan; | ||
503 | int skip; | ||
504 | unsigned long next_delay = 0; | ||
505 | |||
506 | /* | ||
507 | * Avoid re-scheduling when the sdata is going away. | ||
508 | */ | ||
509 | if (!netif_running(sdata->dev)) | ||
510 | return; | ||
511 | |||
512 | switch (local->scan_state) { | ||
513 | case SCAN_SET_CHANNEL: | ||
514 | /* | ||
515 | * Get current scan band. scan_band may be IEEE80211_NUM_BANDS | ||
516 | * after we successfully scanned the last channel of the last | ||
517 | * band (and the last band is supported by the hw) | ||
518 | */ | ||
519 | if (local->scan_band < IEEE80211_NUM_BANDS) | ||
520 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
521 | else | ||
522 | sband = NULL; | ||
523 | |||
524 | /* | ||
525 | * If we are at an unsupported band and have more bands | ||
526 | * left to scan, advance to the next supported one. | ||
527 | */ | ||
528 | while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { | ||
529 | local->scan_band++; | ||
530 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
531 | local->scan_channel_idx = 0; | ||
532 | } | ||
533 | |||
534 | /* if no more bands/channels left, complete scan */ | ||
535 | if (!sband || local->scan_channel_idx >= sband->n_channels) { | ||
536 | ieee80211_scan_completed(local_to_hw(local)); | ||
537 | return; | ||
538 | } | ||
539 | skip = 0; | ||
540 | chan = &sband->channels[local->scan_channel_idx]; | ||
541 | |||
542 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
543 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
544 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
545 | skip = 1; | ||
546 | |||
547 | if (!skip) { | ||
548 | local->scan_channel = chan; | ||
549 | if (ieee80211_hw_config(local)) { | ||
550 | printk(KERN_DEBUG "%s: failed to set freq to " | ||
551 | "%d MHz for scan\n", wiphy_name(local->hw.wiphy), | ||
552 | chan->center_freq); | ||
553 | skip = 1; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | /* advance state machine to next channel/band */ | ||
558 | local->scan_channel_idx++; | ||
559 | if (local->scan_channel_idx >= sband->n_channels) { | ||
560 | /* | ||
561 | * scan_band may end up == IEEE80211_NUM_BANDS, but | ||
562 | * we'll catch that case above and complete the scan | ||
563 | * if that is the case. | ||
564 | */ | ||
565 | local->scan_band++; | ||
566 | local->scan_channel_idx = 0; | ||
567 | } | ||
568 | |||
569 | if (skip) | ||
570 | break; | ||
571 | |||
572 | next_delay = IEEE80211_PROBE_DELAY + | ||
573 | usecs_to_jiffies(local->hw.channel_change_time); | ||
574 | local->scan_state = SCAN_SEND_PROBE; | ||
575 | break; | ||
576 | case SCAN_SEND_PROBE: | ||
577 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
578 | local->scan_state = SCAN_SET_CHANNEL; | ||
579 | |||
580 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
581 | break; | ||
582 | ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, | ||
583 | local->scan_ssid_len); | ||
584 | next_delay = IEEE80211_CHANNEL_TIME; | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
589 | next_delay); | ||
590 | } | ||
591 | |||
592 | |||
593 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | ||
594 | u8 *ssid, size_t ssid_len) | ||
595 | { | ||
596 | struct ieee80211_local *local = scan_sdata->local; | ||
597 | struct ieee80211_sub_if_data *sdata; | ||
598 | |||
599 | if (ssid_len > IEEE80211_MAX_SSID_LEN) | ||
600 | return -EINVAL; | ||
601 | |||
602 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) | ||
603 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS | ||
604 | * BSSID: MACAddress | ||
605 | * SSID | ||
606 | * ScanType: ACTIVE, PASSIVE | ||
607 | * ProbeDelay: delay (in microseconds) to be used prior to transmitting | ||
608 | * a Probe frame during active scanning | ||
609 | * ChannelList | ||
610 | * MinChannelTime (>= ProbeDelay), in TU | ||
611 | * MaxChannelTime: (>= MinChannelTime), in TU | ||
612 | */ | ||
613 | |||
614 | /* MLME-SCAN.confirm | ||
615 | * BSSDescriptionSet | ||
616 | * ResultCode: SUCCESS, INVALID_PARAMETERS | ||
617 | */ | ||
618 | |||
619 | if (local->sw_scanning || local->hw_scanning) { | ||
620 | if (local->scan_sdata == scan_sdata) | ||
621 | return 0; | ||
622 | return -EBUSY; | ||
623 | } | ||
624 | |||
625 | if (local->ops->hw_scan) { | ||
626 | int rc; | ||
627 | |||
628 | local->hw_scanning = true; | ||
629 | rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); | ||
630 | if (rc) { | ||
631 | local->hw_scanning = false; | ||
632 | return rc; | ||
633 | } | ||
634 | local->scan_sdata = scan_sdata; | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | local->sw_scanning = true; | ||
639 | |||
640 | rcu_read_lock(); | ||
641 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
642 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
643 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | ||
644 | netif_tx_stop_all_queues(sdata->dev); | ||
645 | ieee80211_send_nullfunc(local, sdata, 1); | ||
646 | } | ||
647 | } else | ||
648 | netif_tx_stop_all_queues(sdata->dev); | ||
649 | } | ||
650 | rcu_read_unlock(); | ||
651 | |||
652 | if (ssid) { | ||
653 | local->scan_ssid_len = ssid_len; | ||
654 | memcpy(local->scan_ssid, ssid, ssid_len); | ||
655 | } else | ||
656 | local->scan_ssid_len = 0; | ||
657 | local->scan_state = SCAN_SET_CHANNEL; | ||
658 | local->scan_channel_idx = 0; | ||
659 | local->scan_band = IEEE80211_BAND_2GHZ; | ||
660 | local->scan_sdata = scan_sdata; | ||
661 | |||
662 | netif_addr_lock_bh(local->mdev); | ||
663 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
664 | local->ops->configure_filter(local_to_hw(local), | ||
665 | FIF_BCN_PRBRESP_PROMISC, | ||
666 | &local->filter_flags, | ||
667 | local->mdev->mc_count, | ||
668 | local->mdev->mc_list); | ||
669 | netif_addr_unlock_bh(local->mdev); | ||
670 | |||
671 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
672 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
673 | IEEE80211_CHANNEL_TIME); | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | |||
679 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | ||
680 | u8 *ssid, size_t ssid_len) | ||
681 | { | ||
682 | struct ieee80211_local *local = sdata->local; | ||
683 | struct ieee80211_if_sta *ifsta; | ||
684 | |||
685 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
686 | return ieee80211_start_scan(sdata, ssid, ssid_len); | ||
687 | |||
688 | /* | ||
689 | * STA has a state machine that might need to defer scanning | ||
690 | * while it's trying to associate/authenticate, therefore we | ||
691 | * queue it up to the state machine in that case. | ||
692 | */ | ||
693 | |||
694 | if (local->sw_scanning || local->hw_scanning) { | ||
695 | if (local->scan_sdata == sdata) | ||
696 | return 0; | ||
697 | return -EBUSY; | ||
698 | } | ||
699 | |||
700 | ifsta = &sdata->u.sta; | ||
701 | |||
702 | ifsta->scan_ssid_len = ssid_len; | ||
703 | if (ssid_len) | ||
704 | memcpy(ifsta->scan_ssid, ssid, ssid_len); | ||
705 | set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); | ||
706 | queue_work(local->hw.workqueue, &ifsta->work); | ||
707 | |||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | |||
712 | static void ieee80211_scan_add_ies(struct iw_request_info *info, | ||
713 | struct ieee80211_bss *bss, | ||
714 | char **current_ev, char *end_buf) | ||
715 | { | ||
716 | u8 *pos, *end, *next; | ||
717 | struct iw_event iwe; | ||
718 | |||
719 | if (bss == NULL || bss->ies == NULL) | ||
720 | return; | ||
721 | |||
722 | /* | ||
723 | * If needed, fragment the IEs buffer (at IE boundaries) into short | ||
724 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. | ||
725 | */ | ||
726 | pos = bss->ies; | ||
727 | end = pos + bss->ies_len; | ||
728 | |||
729 | while (end - pos > IW_GENERIC_IE_MAX) { | ||
730 | next = pos + 2 + pos[1]; | ||
731 | while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) | ||
732 | next = next + 2 + next[1]; | ||
733 | |||
734 | memset(&iwe, 0, sizeof(iwe)); | ||
735 | iwe.cmd = IWEVGENIE; | ||
736 | iwe.u.data.length = next - pos; | ||
737 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
738 | end_buf, &iwe, pos); | ||
739 | |||
740 | pos = next; | ||
741 | } | ||
742 | |||
743 | if (end > pos) { | ||
744 | memset(&iwe, 0, sizeof(iwe)); | ||
745 | iwe.cmd = IWEVGENIE; | ||
746 | iwe.u.data.length = end - pos; | ||
747 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
748 | end_buf, &iwe, pos); | ||
749 | } | ||
750 | } | ||
751 | |||
752 | |||
753 | static char * | ||
754 | ieee80211_scan_result(struct ieee80211_local *local, | ||
755 | struct iw_request_info *info, | ||
756 | struct ieee80211_bss *bss, | ||
757 | char *current_ev, char *end_buf) | ||
758 | { | ||
759 | struct iw_event iwe; | ||
760 | char *buf; | ||
761 | |||
762 | if (time_after(jiffies, | ||
763 | bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
764 | return current_ev; | ||
765 | |||
766 | memset(&iwe, 0, sizeof(iwe)); | ||
767 | iwe.cmd = SIOCGIWAP; | ||
768 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
769 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | ||
770 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
771 | IW_EV_ADDR_LEN); | ||
772 | |||
773 | memset(&iwe, 0, sizeof(iwe)); | ||
774 | iwe.cmd = SIOCGIWESSID; | ||
775 | if (bss_mesh_cfg(bss)) { | ||
776 | iwe.u.data.length = bss_mesh_id_len(bss); | ||
777 | iwe.u.data.flags = 1; | ||
778 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
779 | &iwe, bss_mesh_id(bss)); | ||
780 | } else { | ||
781 | iwe.u.data.length = bss->ssid_len; | ||
782 | iwe.u.data.flags = 1; | ||
783 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
784 | &iwe, bss->ssid); | ||
785 | } | ||
786 | |||
787 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | ||
788 | || bss_mesh_cfg(bss)) { | ||
789 | memset(&iwe, 0, sizeof(iwe)); | ||
790 | iwe.cmd = SIOCGIWMODE; | ||
791 | if (bss_mesh_cfg(bss)) | ||
792 | iwe.u.mode = IW_MODE_MESH; | ||
793 | else if (bss->capability & WLAN_CAPABILITY_ESS) | ||
794 | iwe.u.mode = IW_MODE_MASTER; | ||
795 | else | ||
796 | iwe.u.mode = IW_MODE_ADHOC; | ||
797 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
798 | &iwe, IW_EV_UINT_LEN); | ||
799 | } | ||
800 | |||
801 | memset(&iwe, 0, sizeof(iwe)); | ||
802 | iwe.cmd = SIOCGIWFREQ; | ||
803 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | ||
804 | iwe.u.freq.e = 0; | ||
805 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
806 | IW_EV_FREQ_LEN); | ||
807 | |||
808 | memset(&iwe, 0, sizeof(iwe)); | ||
809 | iwe.cmd = SIOCGIWFREQ; | ||
810 | iwe.u.freq.m = bss->freq; | ||
811 | iwe.u.freq.e = 6; | ||
812 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
813 | IW_EV_FREQ_LEN); | ||
814 | memset(&iwe, 0, sizeof(iwe)); | ||
815 | iwe.cmd = IWEVQUAL; | ||
816 | iwe.u.qual.qual = bss->qual; | ||
817 | iwe.u.qual.level = bss->signal; | ||
818 | iwe.u.qual.noise = bss->noise; | ||
819 | iwe.u.qual.updated = local->wstats_flags; | ||
820 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
821 | IW_EV_QUAL_LEN); | ||
822 | |||
823 | memset(&iwe, 0, sizeof(iwe)); | ||
824 | iwe.cmd = SIOCGIWENCODE; | ||
825 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | ||
826 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
827 | else | ||
828 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
829 | iwe.u.data.length = 0; | ||
830 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
831 | &iwe, ""); | ||
832 | |||
833 | ieee80211_scan_add_ies(info, bss, ¤t_ev, end_buf); | ||
834 | |||
835 | if (bss->supp_rates_len > 0) { | ||
836 | /* display all supported rates in readable format */ | ||
837 | char *p = current_ev + iwe_stream_lcp_len(info); | ||
838 | int i; | ||
839 | |||
840 | memset(&iwe, 0, sizeof(iwe)); | ||
841 | iwe.cmd = SIOCGIWRATE; | ||
842 | /* Those two flags are ignored... */ | ||
843 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
844 | |||
845 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
846 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | ||
847 | 0x7f) * 500000); | ||
848 | p = iwe_stream_add_value(info, current_ev, p, | ||
849 | end_buf, &iwe, IW_EV_PARAM_LEN); | ||
850 | } | ||
851 | current_ev = p; | ||
852 | } | ||
853 | |||
854 | buf = kmalloc(30, GFP_ATOMIC); | ||
855 | if (buf) { | ||
856 | memset(&iwe, 0, sizeof(iwe)); | ||
857 | iwe.cmd = IWEVCUSTOM; | ||
858 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | ||
859 | iwe.u.data.length = strlen(buf); | ||
860 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
861 | &iwe, buf); | ||
862 | memset(&iwe, 0, sizeof(iwe)); | ||
863 | iwe.cmd = IWEVCUSTOM; | ||
864 | sprintf(buf, " Last beacon: %dms ago", | ||
865 | jiffies_to_msecs(jiffies - bss->last_update)); | ||
866 | iwe.u.data.length = strlen(buf); | ||
867 | current_ev = iwe_stream_add_point(info, current_ev, | ||
868 | end_buf, &iwe, buf); | ||
869 | kfree(buf); | ||
870 | } | ||
871 | |||
872 | if (bss_mesh_cfg(bss)) { | ||
873 | u8 *cfg = bss_mesh_cfg(bss); | ||
874 | buf = kmalloc(50, GFP_ATOMIC); | ||
875 | if (buf) { | ||
876 | memset(&iwe, 0, sizeof(iwe)); | ||
877 | iwe.cmd = IWEVCUSTOM; | ||
878 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | ||
879 | iwe.u.data.length = strlen(buf); | ||
880 | current_ev = iwe_stream_add_point(info, current_ev, | ||
881 | end_buf, | ||
882 | &iwe, buf); | ||
883 | sprintf(buf, "Path Selection Protocol ID: " | ||
884 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | ||
885 | cfg[4]); | ||
886 | iwe.u.data.length = strlen(buf); | ||
887 | current_ev = iwe_stream_add_point(info, current_ev, | ||
888 | end_buf, | ||
889 | &iwe, buf); | ||
890 | sprintf(buf, "Path Selection Metric ID: " | ||
891 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | ||
892 | cfg[8]); | ||
893 | iwe.u.data.length = strlen(buf); | ||
894 | current_ev = iwe_stream_add_point(info, current_ev, | ||
895 | end_buf, | ||
896 | &iwe, buf); | ||
897 | sprintf(buf, "Congestion Control Mode ID: " | ||
898 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
899 | cfg[11], cfg[12]); | ||
900 | iwe.u.data.length = strlen(buf); | ||
901 | current_ev = iwe_stream_add_point(info, current_ev, | ||
902 | end_buf, | ||
903 | &iwe, buf); | ||
904 | sprintf(buf, "Channel Precedence: " | ||
905 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | ||
906 | cfg[15], cfg[16]); | ||
907 | iwe.u.data.length = strlen(buf); | ||
908 | current_ev = iwe_stream_add_point(info, current_ev, | ||
909 | end_buf, | ||
910 | &iwe, buf); | ||
911 | kfree(buf); | ||
912 | } | ||
913 | } | ||
914 | |||
915 | return current_ev; | ||
916 | } | ||
917 | |||
918 | |||
919 | int ieee80211_scan_results(struct ieee80211_local *local, | ||
920 | struct iw_request_info *info, | ||
921 | char *buf, size_t len) | ||
922 | { | ||
923 | char *current_ev = buf; | ||
924 | char *end_buf = buf + len; | ||
925 | struct ieee80211_bss *bss; | ||
926 | |||
927 | spin_lock_bh(&local->bss_lock); | ||
928 | list_for_each_entry(bss, &local->bss_list, list) { | ||
929 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | ||
930 | spin_unlock_bh(&local->bss_lock); | ||
931 | return -E2BIG; | ||
932 | } | ||
933 | current_ev = ieee80211_scan_result(local, info, bss, | ||
934 | current_ev, end_buf); | ||
935 | } | ||
936 | spin_unlock_bh(&local->bss_lock); | ||
937 | return current_ev - buf; | ||
938 | } | ||
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c new file mode 100644 index 000000000000..f72bad636d8e --- /dev/null +++ b/net/mac80211/spectmgmt.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * spectrum management | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2007-2008, Intel Corporation | ||
10 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/ieee80211.h> | ||
18 | #include <net/wireless.h> | ||
19 | #include <net/mac80211.h> | ||
20 | #include "ieee80211_i.h" | ||
21 | #include "sta_info.h" | ||
22 | #include "wme.h" | ||
23 | |||
24 | static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, | ||
25 | struct ieee80211_msrment_ie *request_ie, | ||
26 | const u8 *da, const u8 *bssid, | ||
27 | u8 dialog_token) | ||
28 | { | ||
29 | struct ieee80211_local *local = sdata->local; | ||
30 | struct sk_buff *skb; | ||
31 | struct ieee80211_mgmt *msr_report; | ||
32 | |||
33 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | ||
34 | sizeof(struct ieee80211_msrment_ie)); | ||
35 | |||
36 | if (!skb) { | ||
37 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
38 | "measurement report frame\n", sdata->dev->name); | ||
39 | return; | ||
40 | } | ||
41 | |||
42 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | ||
44 | memset(msr_report, 0, 24); | ||
45 | memcpy(msr_report->da, da, ETH_ALEN); | ||
46 | memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
47 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | ||
48 | msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
49 | IEEE80211_STYPE_ACTION); | ||
50 | |||
51 | skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); | ||
52 | msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
53 | msr_report->u.action.u.measurement.action_code = | ||
54 | WLAN_ACTION_SPCT_MSR_RPRT; | ||
55 | msr_report->u.action.u.measurement.dialog_token = dialog_token; | ||
56 | |||
57 | msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; | ||
58 | msr_report->u.action.u.measurement.length = | ||
59 | sizeof(struct ieee80211_msrment_ie); | ||
60 | |||
61 | memset(&msr_report->u.action.u.measurement.msr_elem, 0, | ||
62 | sizeof(struct ieee80211_msrment_ie)); | ||
63 | msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; | ||
64 | msr_report->u.action.u.measurement.msr_elem.mode |= | ||
65 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | ||
66 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | ||
67 | |||
68 | ieee80211_tx_skb(sdata, skb, 0); | ||
69 | } | ||
70 | |||
71 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | ||
72 | struct ieee80211_mgmt *mgmt, | ||
73 | size_t len) | ||
74 | { | ||
75 | /* | ||
76 | * Ignoring measurement request is spec violation. | ||
77 | * Mandatory measurements must be reported optional | ||
78 | * measurements might be refused or reported incapable | ||
79 | * For now just refuse | ||
80 | * TODO: Answer basic measurement as unmeasured | ||
81 | */ | ||
82 | ieee80211_send_refuse_measurement_request(sdata, | ||
83 | &mgmt->u.action.u.measurement.msr_elem, | ||
84 | mgmt->sa, mgmt->bssid, | ||
85 | mgmt->u.action.u.measurement.dialog_token); | ||
86 | } | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2ba653b9d69..7fef8ea1f5ec 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -73,11 +73,11 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
73 | { | 73 | { |
74 | struct sta_info *s; | 74 | struct sta_info *s; |
75 | 75 | ||
76 | s = local->sta_hash[STA_HASH(sta->addr)]; | 76 | s = local->sta_hash[STA_HASH(sta->sta.addr)]; |
77 | if (!s) | 77 | if (!s) |
78 | return -ENOENT; | 78 | return -ENOENT; |
79 | if (s == sta) { | 79 | if (s == sta) { |
80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], | 80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], |
81 | s->hnext); | 81 | s->hnext); |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
@@ -93,26 +93,19 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) |
97 | u8 *addr) | ||
98 | { | 97 | { |
99 | struct sta_info *sta; | 98 | struct sta_info *sta; |
100 | 99 | ||
101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 100 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
102 | while (sta) { | 101 | while (sta) { |
103 | if (compare_ether_addr(sta->addr, addr) == 0) | 102 | if (compare_ether_addr(sta->sta.addr, addr) == 0) |
104 | break; | 103 | break; |
105 | sta = rcu_dereference(sta->hnext); | 104 | sta = rcu_dereference(sta->hnext); |
106 | } | 105 | } |
107 | return sta; | 106 | return sta; |
108 | } | 107 | } |
109 | 108 | ||
110 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | ||
111 | { | ||
112 | return __sta_info_find(local, addr); | ||
113 | } | ||
114 | EXPORT_SYMBOL(sta_info_get); | ||
115 | |||
116 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 109 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, |
117 | struct net_device *dev) | 110 | struct net_device *dev) |
118 | { | 111 | { |
@@ -146,12 +139,12 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
146 | { | 139 | { |
147 | DECLARE_MAC_BUF(mbuf); | 140 | DECLARE_MAC_BUF(mbuf); |
148 | 141 | ||
149 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | 142 | rate_control_free_sta(sta); |
150 | rate_control_put(sta->rate_ctrl); | 143 | rate_control_put(sta->rate_ctrl); |
151 | 144 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 145 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
153 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", | 146 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", |
154 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 147 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
155 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 148 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
156 | 149 | ||
157 | kfree(sta); | 150 | kfree(sta); |
@@ -219,8 +212,8 @@ void sta_info_destroy(struct sta_info *sta) | |||
219 | static void sta_info_hash_add(struct ieee80211_local *local, | 212 | static void sta_info_hash_add(struct ieee80211_local *local, |
220 | struct sta_info *sta) | 213 | struct sta_info *sta) |
221 | { | 214 | { |
222 | sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; | 215 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
223 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta); | 216 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
224 | } | 217 | } |
225 | 218 | ||
226 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 219 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
@@ -231,20 +224,20 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
231 | int i; | 224 | int i; |
232 | DECLARE_MAC_BUF(mbuf); | 225 | DECLARE_MAC_BUF(mbuf); |
233 | 226 | ||
234 | sta = kzalloc(sizeof(*sta), gfp); | 227 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); |
235 | if (!sta) | 228 | if (!sta) |
236 | return NULL; | 229 | return NULL; |
237 | 230 | ||
238 | spin_lock_init(&sta->lock); | 231 | spin_lock_init(&sta->lock); |
239 | spin_lock_init(&sta->flaglock); | 232 | spin_lock_init(&sta->flaglock); |
240 | 233 | ||
241 | memcpy(sta->addr, addr, ETH_ALEN); | 234 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
242 | sta->local = local; | 235 | sta->local = local; |
243 | sta->sdata = sdata; | 236 | sta->sdata = sdata; |
244 | 237 | ||
245 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 238 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); |
246 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 239 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
247 | gfp); | 240 | &sta->sta, gfp); |
248 | if (!sta->rate_ctrl_priv) { | 241 | if (!sta->rate_ctrl_priv) { |
249 | rate_control_put(sta->rate_ctrl); | 242 | rate_control_put(sta->rate_ctrl); |
250 | kfree(sta); | 243 | kfree(sta); |
@@ -271,7 +264,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
271 | 264 | ||
272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 265 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", | 266 | printk(KERN_DEBUG "%s: Allocated STA %s\n", |
274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 267 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 268 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
276 | 269 | ||
277 | #ifdef CONFIG_MAC80211_MESH | 270 | #ifdef CONFIG_MAC80211_MESH |
@@ -300,15 +293,15 @@ int sta_info_insert(struct sta_info *sta) | |||
300 | goto out_free; | 293 | goto out_free; |
301 | } | 294 | } |
302 | 295 | ||
303 | if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 || | 296 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || |
304 | is_multicast_ether_addr(sta->addr))) { | 297 | is_multicast_ether_addr(sta->sta.addr))) { |
305 | err = -EINVAL; | 298 | err = -EINVAL; |
306 | goto out_free; | 299 | goto out_free; |
307 | } | 300 | } |
308 | 301 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 302 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 303 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->addr)) { | 304 | if (sta_info_get(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 305 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 306 | err = -EEXIST; |
314 | goto out_free; | 307 | goto out_free; |
@@ -319,18 +312,18 @@ int sta_info_insert(struct sta_info *sta) | |||
319 | 312 | ||
320 | /* notify driver */ | 313 | /* notify driver */ |
321 | if (local->ops->sta_notify) { | 314 | if (local->ops->sta_notify) { |
322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 315 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
323 | sdata = container_of(sdata->bss, | 316 | sdata = container_of(sdata->bss, |
324 | struct ieee80211_sub_if_data, | 317 | struct ieee80211_sub_if_data, |
325 | u.ap); | 318 | u.ap); |
326 | 319 | ||
327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 320 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
328 | STA_NOTIFY_ADD, sta->addr); | 321 | STA_NOTIFY_ADD, &sta->sta); |
329 | } | 322 | } |
330 | 323 | ||
331 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 324 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
332 | printk(KERN_DEBUG "%s: Inserted STA %s\n", | 325 | printk(KERN_DEBUG "%s: Inserted STA %s\n", |
333 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); | 326 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr)); |
334 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 327 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
335 | 328 | ||
336 | spin_unlock_irqrestore(&local->sta_lock, flags); | 329 | spin_unlock_irqrestore(&local->sta_lock, flags); |
@@ -379,11 +372,12 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | |||
379 | { | 372 | { |
380 | BUG_ON(!bss); | 373 | BUG_ON(!bss); |
381 | 374 | ||
382 | __bss_tim_set(bss, sta->aid); | 375 | __bss_tim_set(bss, sta->sta.aid); |
383 | 376 | ||
384 | if (sta->local->ops->set_tim) { | 377 | if (sta->local->ops->set_tim) { |
385 | sta->local->tim_in_locked_section = true; | 378 | sta->local->tim_in_locked_section = true; |
386 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | 379 | sta->local->ops->set_tim(local_to_hw(sta->local), |
380 | &sta->sta, true); | ||
387 | sta->local->tim_in_locked_section = false; | 381 | sta->local->tim_in_locked_section = false; |
388 | } | 382 | } |
389 | } | 383 | } |
@@ -404,11 +398,12 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | |||
404 | { | 398 | { |
405 | BUG_ON(!bss); | 399 | BUG_ON(!bss); |
406 | 400 | ||
407 | __bss_tim_clear(bss, sta->aid); | 401 | __bss_tim_clear(bss, sta->sta.aid); |
408 | 402 | ||
409 | if (sta->local->ops->set_tim) { | 403 | if (sta->local->ops->set_tim) { |
410 | sta->local->tim_in_locked_section = true; | 404 | sta->local->tim_in_locked_section = true; |
411 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | 405 | sta->local->ops->set_tim(local_to_hw(sta->local), |
406 | &sta->sta, false); | ||
412 | sta->local->tim_in_locked_section = false; | 407 | sta->local->tim_in_locked_section = false; |
413 | } | 408 | } |
414 | } | 409 | } |
@@ -424,7 +419,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
424 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 419 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
425 | } | 420 | } |
426 | 421 | ||
427 | void __sta_info_unlink(struct sta_info **sta) | 422 | static void __sta_info_unlink(struct sta_info **sta) |
428 | { | 423 | { |
429 | struct ieee80211_local *local = (*sta)->local; | 424 | struct ieee80211_local *local = (*sta)->local; |
430 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | 425 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; |
@@ -456,13 +451,13 @@ void __sta_info_unlink(struct sta_info **sta) | |||
456 | local->num_sta--; | 451 | local->num_sta--; |
457 | 452 | ||
458 | if (local->ops->sta_notify) { | 453 | if (local->ops->sta_notify) { |
459 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 454 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
460 | sdata = container_of(sdata->bss, | 455 | sdata = container_of(sdata->bss, |
461 | struct ieee80211_sub_if_data, | 456 | struct ieee80211_sub_if_data, |
462 | u.ap); | 457 | u.ap); |
463 | 458 | ||
464 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 459 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
465 | STA_NOTIFY_REMOVE, (*sta)->addr); | 460 | STA_NOTIFY_REMOVE, &(*sta)->sta); |
466 | } | 461 | } |
467 | 462 | ||
468 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 463 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -474,7 +469,7 @@ void __sta_info_unlink(struct sta_info **sta) | |||
474 | 469 | ||
475 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 470 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
476 | printk(KERN_DEBUG "%s: Removed STA %s\n", | 471 | printk(KERN_DEBUG "%s: Removed STA %s\n", |
477 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr)); | 472 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr)); |
478 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 473 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
479 | 474 | ||
480 | /* | 475 | /* |
@@ -570,7 +565,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
570 | local->total_ps_buffered--; | 565 | local->total_ps_buffered--; |
571 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 566 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
572 | printk(KERN_DEBUG "Buffered frame expired (STA " | 567 | printk(KERN_DEBUG "Buffered frame expired (STA " |
573 | "%s)\n", print_mac(mac, sta->addr)); | 568 | "%s)\n", print_mac(mac, sta->sta.addr)); |
574 | #endif | 569 | #endif |
575 | dev_kfree_skb(skb); | 570 | dev_kfree_skb(skb); |
576 | 571 | ||
@@ -640,7 +635,12 @@ static void sta_info_debugfs_add_work(struct work_struct *work) | |||
640 | 635 | ||
641 | spin_lock_irqsave(&local->sta_lock, flags); | 636 | spin_lock_irqsave(&local->sta_lock, flags); |
642 | list_for_each_entry(tmp, &local->sta_list, list) { | 637 | list_for_each_entry(tmp, &local->sta_list, list) { |
643 | if (!tmp->debugfs.dir) { | 638 | /* |
639 | * debugfs.add_has_run will be set by | ||
640 | * ieee80211_sta_debugfs_add regardless | ||
641 | * of what else it does. | ||
642 | */ | ||
643 | if (!tmp->debugfs.add_has_run) { | ||
644 | sta = tmp; | 644 | sta = tmp; |
645 | __sta_info_pin(sta); | 645 | __sta_info_pin(sta); |
646 | break; | 646 | break; |
@@ -802,3 +802,40 @@ void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) | |||
802 | schedule_work(&local->sta_flush_work); | 802 | schedule_work(&local->sta_flush_work); |
803 | spin_unlock_irqrestore(&local->sta_lock, flags); | 803 | spin_unlock_irqrestore(&local->sta_lock, flags); |
804 | } | 804 | } |
805 | |||
806 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | ||
807 | unsigned long exp_time) | ||
808 | { | ||
809 | struct ieee80211_local *local = sdata->local; | ||
810 | struct sta_info *sta, *tmp; | ||
811 | LIST_HEAD(tmp_list); | ||
812 | DECLARE_MAC_BUF(mac); | ||
813 | unsigned long flags; | ||
814 | |||
815 | spin_lock_irqsave(&local->sta_lock, flags); | ||
816 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | ||
817 | if (time_after(jiffies, sta->last_rx + exp_time)) { | ||
818 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
819 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | ||
820 | sdata->dev->name, print_mac(mac, sta->sta.addr)); | ||
821 | #endif | ||
822 | __sta_info_unlink(&sta); | ||
823 | if (sta) | ||
824 | list_add(&sta->list, &tmp_list); | ||
825 | } | ||
826 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
827 | |||
828 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
829 | sta_info_destroy(sta); | ||
830 | } | ||
831 | |||
832 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | ||
833 | const u8 *addr) | ||
834 | { | ||
835 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); | ||
836 | |||
837 | if (!sta) | ||
838 | return NULL; | ||
839 | return &sta->sta; | ||
840 | } | ||
841 | EXPORT_SYMBOL(ieee80211_find_sta); | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 109db787ccb7..168a39a298bd 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -167,8 +167,6 @@ struct sta_ampdu_mlme { | |||
167 | * @lock: used for locking all fields that require locking, see comments | 167 | * @lock: used for locking all fields that require locking, see comments |
168 | * in the header file. | 168 | * in the header file. |
169 | * @flaglock: spinlock for flags accesses | 169 | * @flaglock: spinlock for flags accesses |
170 | * @ht_info: HT capabilities of this STA | ||
171 | * @supp_rates: Bitmap of supported rates (per band) | ||
172 | * @addr: MAC address of this STA | 170 | * @addr: MAC address of this STA |
173 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), | 171 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), |
174 | * only used in AP (and IBSS?) mode | 172 | * only used in AP (and IBSS?) mode |
@@ -191,20 +189,15 @@ struct sta_ampdu_mlme { | |||
191 | * @last_qual: qual of last received frame from this STA | 189 | * @last_qual: qual of last received frame from this STA |
192 | * @last_noise: noise of last received frame from this STA | 190 | * @last_noise: noise of last received frame from this STA |
193 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 191 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
194 | * @wme_rx_queue: TBD | ||
195 | * @tx_filtered_count: TBD | 192 | * @tx_filtered_count: TBD |
196 | * @tx_retry_failed: TBD | 193 | * @tx_retry_failed: TBD |
197 | * @tx_retry_count: TBD | 194 | * @tx_retry_count: TBD |
198 | * @tx_num_consecutive_failures: TBD | ||
199 | * @tx_num_mpdu_ok: TBD | ||
200 | * @tx_num_mpdu_fail: TBD | ||
201 | * @fail_avg: moving percentage of failed MSDUs | 195 | * @fail_avg: moving percentage of failed MSDUs |
202 | * @tx_packets: number of RX/TX MSDUs | 196 | * @tx_packets: number of RX/TX MSDUs |
203 | * @tx_bytes: TBD | 197 | * @tx_bytes: TBD |
204 | * @tx_fragments: number of transmitted MPDUs | 198 | * @tx_fragments: number of transmitted MPDUs |
205 | * @txrate_idx: TBD | 199 | * @last_txrate_idx: Index of the last used transmit rate |
206 | * @last_txrate_idx: TBD | 200 | * @tid_seq: TBD |
207 | * @wme_tx_queue: TBD | ||
208 | * @ampdu_mlme: TBD | 201 | * @ampdu_mlme: TBD |
209 | * @timer_to_tid: identity mapping to ID timers | 202 | * @timer_to_tid: identity mapping to ID timers |
210 | * @tid_to_tx_q: map tid to tx queue | 203 | * @tid_to_tx_q: map tid to tx queue |
@@ -217,6 +210,7 @@ struct sta_ampdu_mlme { | |||
217 | * @plink_timeout: TBD | 210 | * @plink_timeout: TBD |
218 | * @plink_timer: TBD | 211 | * @plink_timer: TBD |
219 | * @debugfs: debug filesystem info | 212 | * @debugfs: debug filesystem info |
213 | * @sta: station information we share with the driver | ||
220 | */ | 214 | */ |
221 | struct sta_info { | 215 | struct sta_info { |
222 | /* General information, mostly static */ | 216 | /* General information, mostly static */ |
@@ -229,10 +223,7 @@ struct sta_info { | |||
229 | void *rate_ctrl_priv; | 223 | void *rate_ctrl_priv; |
230 | spinlock_t lock; | 224 | spinlock_t lock; |
231 | spinlock_t flaglock; | 225 | spinlock_t flaglock; |
232 | struct ieee80211_ht_info ht_info; | 226 | |
233 | u64 supp_rates[IEEE80211_NUM_BANDS]; | ||
234 | u8 addr[ETH_ALEN]; | ||
235 | u16 aid; | ||
236 | u16 listen_interval; | 227 | u16 listen_interval; |
237 | 228 | ||
238 | /* | 229 | /* |
@@ -265,17 +256,10 @@ struct sta_info { | |||
265 | int last_qual; | 256 | int last_qual; |
266 | int last_noise; | 257 | int last_noise; |
267 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 258 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
268 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
269 | unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; | ||
270 | #endif | ||
271 | 259 | ||
272 | /* Updated from TX status path only, no locking requirements */ | 260 | /* Updated from TX status path only, no locking requirements */ |
273 | unsigned long tx_filtered_count; | 261 | unsigned long tx_filtered_count; |
274 | unsigned long tx_retry_failed, tx_retry_count; | 262 | unsigned long tx_retry_failed, tx_retry_count; |
275 | /* TODO: update in generic code not rate control? */ | ||
276 | u32 tx_num_consecutive_failures; | ||
277 | u32 tx_num_mpdu_ok; | ||
278 | u32 tx_num_mpdu_fail; | ||
279 | /* moving percentage of failed MSDUs */ | 263 | /* moving percentage of failed MSDUs */ |
280 | unsigned int fail_avg; | 264 | unsigned int fail_avg; |
281 | 265 | ||
@@ -283,12 +267,8 @@ struct sta_info { | |||
283 | unsigned long tx_packets; | 267 | unsigned long tx_packets; |
284 | unsigned long tx_bytes; | 268 | unsigned long tx_bytes; |
285 | unsigned long tx_fragments; | 269 | unsigned long tx_fragments; |
286 | int txrate_idx; | 270 | unsigned int last_txrate_idx; |
287 | int last_txrate_idx; | ||
288 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 271 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
289 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
290 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | ||
291 | #endif | ||
292 | 272 | ||
293 | /* | 273 | /* |
294 | * Aggregation information, locked with lock. | 274 | * Aggregation information, locked with lock. |
@@ -319,13 +299,13 @@ struct sta_info { | |||
319 | struct dentry *num_ps_buf_frames; | 299 | struct dentry *num_ps_buf_frames; |
320 | struct dentry *inactive_ms; | 300 | struct dentry *inactive_ms; |
321 | struct dentry *last_seq_ctrl; | 301 | struct dentry *last_seq_ctrl; |
322 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
323 | struct dentry *wme_rx_queue; | ||
324 | struct dentry *wme_tx_queue; | ||
325 | #endif | ||
326 | struct dentry *agg_status; | 302 | struct dentry *agg_status; |
303 | bool add_has_run; | ||
327 | } debugfs; | 304 | } debugfs; |
328 | #endif | 305 | #endif |
306 | |||
307 | /* keep last! */ | ||
308 | struct ieee80211_sta sta; | ||
329 | }; | 309 | }; |
330 | 310 | ||
331 | static inline enum plink_state sta_plink_state(struct sta_info *sta) | 311 | static inline enum plink_state sta_plink_state(struct sta_info *sta) |
@@ -425,7 +405,7 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
425 | /* | 405 | /* |
426 | * Get a STA info, must have be under RCU read lock. | 406 | * Get a STA info, must have be under RCU read lock. |
427 | */ | 407 | */ |
428 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr); | 408 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); |
429 | /* | 409 | /* |
430 | * Get STA info by index, BROKEN! | 410 | * Get STA info by index, BROKEN! |
431 | */ | 411 | */ |
@@ -451,7 +431,6 @@ int sta_info_insert(struct sta_info *sta); | |||
451 | * has already unlinked it. | 431 | * has already unlinked it. |
452 | */ | 432 | */ |
453 | void sta_info_unlink(struct sta_info **sta); | 433 | void sta_info_unlink(struct sta_info **sta); |
454 | void __sta_info_unlink(struct sta_info **sta); | ||
455 | 434 | ||
456 | void sta_info_destroy(struct sta_info *sta); | 435 | void sta_info_destroy(struct sta_info *sta); |
457 | void sta_info_set_tim_bit(struct sta_info *sta); | 436 | void sta_info_set_tim_bit(struct sta_info *sta); |
@@ -463,5 +442,7 @@ void sta_info_stop(struct ieee80211_local *local); | |||
463 | int sta_info_flush(struct ieee80211_local *local, | 442 | int sta_info_flush(struct ieee80211_local *local, |
464 | struct ieee80211_sub_if_data *sdata); | 443 | struct ieee80211_sub_if_data *sdata); |
465 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); | 444 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); |
445 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | ||
446 | unsigned long exp_time); | ||
466 | 447 | ||
467 | #endif /* STA_INFO_H */ | 448 | #endif /* STA_INFO_H */ |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 995f7af3d25e..34b32bc8f609 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -304,7 +304,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
305 | u8 bcast[ETH_ALEN] = | 305 | u8 bcast[ETH_ALEN] = |
306 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 306 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
307 | u8 *sta_addr = key->sta->addr; | 307 | u8 *sta_addr = key->sta->sta.addr; |
308 | 308 | ||
309 | if (is_multicast_ether_addr(ra)) | 309 | if (is_multicast_ether_addr(ra)) |
310 | sta_addr = bcast; | 310 | sta_addr = bcast; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4788f7b91f49..1460537faf33 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -38,43 +38,6 @@ | |||
38 | 38 | ||
39 | /* misc utils */ | 39 | /* misc utils */ |
40 | 40 | ||
41 | #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP | ||
42 | static void ieee80211_dump_frame(const char *ifname, const char *title, | ||
43 | const struct sk_buff *skb) | ||
44 | { | ||
45 | const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
46 | unsigned int hdrlen; | ||
47 | DECLARE_MAC_BUF(mac); | ||
48 | |||
49 | printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); | ||
50 | if (skb->len < 4) { | ||
51 | printk("\n"); | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
56 | if (hdrlen > skb->len) | ||
57 | hdrlen = skb->len; | ||
58 | if (hdrlen >= 4) | ||
59 | printk(" FC=0x%04x DUR=0x%04x", | ||
60 | le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); | ||
61 | if (hdrlen >= 10) | ||
62 | printk(" A1=%s", print_mac(mac, hdr->addr1)); | ||
63 | if (hdrlen >= 16) | ||
64 | printk(" A2=%s", print_mac(mac, hdr->addr2)); | ||
65 | if (hdrlen >= 24) | ||
66 | printk(" A3=%s", print_mac(mac, hdr->addr3)); | ||
67 | if (hdrlen >= 30) | ||
68 | printk(" A4=%s", print_mac(mac, hdr->addr4)); | ||
69 | printk("\n"); | ||
70 | } | ||
71 | #else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ | ||
72 | static inline void ieee80211_dump_frame(const char *ifname, const char *title, | ||
73 | struct sk_buff *skb) | ||
74 | { | ||
75 | } | ||
76 | #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ | ||
77 | |||
78 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | 41 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, |
79 | int next_frag_len) | 42 | int next_frag_len) |
80 | { | 43 | { |
@@ -82,6 +45,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
82 | struct ieee80211_rate *txrate; | 45 | struct ieee80211_rate *txrate; |
83 | struct ieee80211_local *local = tx->local; | 46 | struct ieee80211_local *local = tx->local; |
84 | struct ieee80211_supported_band *sband; | 47 | struct ieee80211_supported_band *sband; |
48 | struct ieee80211_hdr *hdr; | ||
85 | 49 | ||
86 | sband = local->hw.wiphy->bands[tx->channel->band]; | 50 | sband = local->hw.wiphy->bands[tx->channel->band]; |
87 | txrate = &sband->bitrates[tx->rate_idx]; | 51 | txrate = &sband->bitrates[tx->rate_idx]; |
@@ -107,10 +71,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
107 | * at the highest possible rate belonging to the PHY rates in the | 71 | * at the highest possible rate belonging to the PHY rates in the |
108 | * BSSBasicRateSet | 72 | * BSSBasicRateSet |
109 | */ | 73 | */ |
110 | 74 | hdr = (struct ieee80211_hdr *)tx->skb->data; | |
111 | if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) { | 75 | if (ieee80211_is_ctl(hdr->frame_control)) { |
112 | /* TODO: These control frames are not currently sent by | 76 | /* TODO: These control frames are not currently sent by |
113 | * 80211.o, but should they be implemented, this function | 77 | * mac80211, but should they be implemented, this function |
114 | * needs to be updated to support duration field calculation. | 78 | * needs to be updated to support duration field calculation. |
115 | * | 79 | * |
116 | * RTS: time needed to transmit pending data/mgmt frame plus | 80 | * RTS: time needed to transmit pending data/mgmt frame plus |
@@ -152,7 +116,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
152 | if (r->bitrate > txrate->bitrate) | 116 | if (r->bitrate > txrate->bitrate) |
153 | break; | 117 | break; |
154 | 118 | ||
155 | if (tx->sdata->basic_rates & BIT(i)) | 119 | if (tx->sdata->bss_conf.basic_rates & BIT(i)) |
156 | rate = r->bitrate; | 120 | rate = r->bitrate; |
157 | 121 | ||
158 | switch (sband->band) { | 122 | switch (sband->band) { |
@@ -201,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
201 | return cpu_to_le16(dur); | 165 | return cpu_to_le16(dur); |
202 | } | 166 | } |
203 | 167 | ||
204 | static int inline is_ieee80211_device(struct net_device *dev, | 168 | static int inline is_ieee80211_device(struct ieee80211_local *local, |
205 | struct net_device *master) | 169 | struct net_device *dev) |
206 | { | 170 | { |
207 | return (wdev_priv(dev->ieee80211_ptr) == | 171 | return local == wdev_priv(dev->ieee80211_ptr); |
208 | wdev_priv(master->ieee80211_ptr)); | ||
209 | } | 172 | } |
210 | 173 | ||
211 | /* tx handlers */ | 174 | /* tx handlers */ |
@@ -213,21 +176,19 @@ static int inline is_ieee80211_device(struct net_device *dev, | |||
213 | static ieee80211_tx_result debug_noinline | 176 | static ieee80211_tx_result debug_noinline |
214 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | 177 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) |
215 | { | 178 | { |
216 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 179 | |
217 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 180 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
218 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
219 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 181 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
220 | u32 sta_flags; | 182 | u32 sta_flags; |
221 | 183 | ||
222 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 184 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
223 | return TX_CONTINUE; | 185 | return TX_CONTINUE; |
224 | 186 | ||
225 | if (unlikely(tx->local->sta_sw_scanning) && | 187 | if (unlikely(tx->local->sw_scanning) && |
226 | ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || | 188 | !ieee80211_is_probe_req(hdr->frame_control)) |
227 | (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ)) | ||
228 | return TX_DROP; | 189 | return TX_DROP; |
229 | 190 | ||
230 | if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) | 191 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
231 | return TX_CONTINUE; | 192 | return TX_CONTINUE; |
232 | 193 | ||
233 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) | 194 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) |
@@ -237,8 +198,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
237 | 198 | ||
238 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 199 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
239 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && | 200 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && |
240 | tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 201 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
241 | (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { | 202 | ieee80211_is_data(hdr->frame_control))) { |
242 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 203 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
243 | DECLARE_MAC_BUF(mac); | 204 | DECLARE_MAC_BUF(mac); |
244 | printk(KERN_DEBUG "%s: dropped data frame to not " | 205 | printk(KERN_DEBUG "%s: dropped data frame to not " |
@@ -249,9 +210,9 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
249 | return TX_DROP; | 210 | return TX_DROP; |
250 | } | 211 | } |
251 | } else { | 212 | } else { |
252 | if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 213 | if (unlikely(ieee80211_is_data(hdr->frame_control) && |
253 | tx->local->num_sta == 0 && | 214 | tx->local->num_sta == 0 && |
254 | tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) { | 215 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { |
255 | /* | 216 | /* |
256 | * No associated STAs - no need to send multicast | 217 | * No associated STAs - no need to send multicast |
257 | * frames. | 218 | * frames. |
@@ -282,7 +243,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
282 | 243 | ||
283 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 244 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
284 | struct ieee80211_if_ap *ap; | 245 | struct ieee80211_if_ap *ap; |
285 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 246 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
286 | continue; | 247 | continue; |
287 | ap = &sdata->u.ap; | 248 | ap = &sdata->u.ap; |
288 | skb = skb_dequeue(&ap->ps_bc_buf); | 249 | skb = skb_dequeue(&ap->ps_bc_buf); |
@@ -315,6 +276,7 @@ static ieee80211_tx_result | |||
315 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | 276 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) |
316 | { | 277 | { |
317 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 278 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
279 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
318 | 280 | ||
319 | /* | 281 | /* |
320 | * broadcast/multicast frame | 282 | * broadcast/multicast frame |
@@ -329,7 +291,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
329 | return TX_CONTINUE; | 291 | return TX_CONTINUE; |
330 | 292 | ||
331 | /* no buffering for ordered frames */ | 293 | /* no buffering for ordered frames */ |
332 | if (tx->fc & IEEE80211_FCTL_ORDER) | 294 | if (ieee80211_has_order(hdr->frame_control)) |
333 | return TX_CONTINUE; | 295 | return TX_CONTINUE; |
334 | 296 | ||
335 | /* no stations in PS mode */ | 297 | /* no stations in PS mode */ |
@@ -367,12 +329,11 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
367 | { | 329 | { |
368 | struct sta_info *sta = tx->sta; | 330 | struct sta_info *sta = tx->sta; |
369 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 331 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
370 | u32 staflags; | 333 | u32 staflags; |
371 | DECLARE_MAC_BUF(mac); | 334 | DECLARE_MAC_BUF(mac); |
372 | 335 | ||
373 | if (unlikely(!sta || | 336 | if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) |
374 | ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && | ||
375 | (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) | ||
376 | return TX_CONTINUE; | 337 | return TX_CONTINUE; |
377 | 338 | ||
378 | staflags = get_sta_flags(sta); | 339 | staflags = get_sta_flags(sta); |
@@ -382,7 +343,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
382 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 343 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
383 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " | 344 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " |
384 | "before %d)\n", | 345 | "before %d)\n", |
385 | print_mac(mac, sta->addr), sta->aid, | 346 | print_mac(mac, sta->sta.addr), sta->sta.aid, |
386 | skb_queue_len(&sta->ps_tx_buf)); | 347 | skb_queue_len(&sta->ps_tx_buf)); |
387 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 348 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
388 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 349 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
@@ -393,7 +354,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
393 | if (net_ratelimit()) { | 354 | if (net_ratelimit()) { |
394 | printk(KERN_DEBUG "%s: STA %s TX " | 355 | printk(KERN_DEBUG "%s: STA %s TX " |
395 | "buffer full - dropping oldest frame\n", | 356 | "buffer full - dropping oldest frame\n", |
396 | tx->dev->name, print_mac(mac, sta->addr)); | 357 | tx->dev->name, print_mac(mac, sta->sta.addr)); |
397 | } | 358 | } |
398 | #endif | 359 | #endif |
399 | dev_kfree_skb(old); | 360 | dev_kfree_skb(old); |
@@ -412,7 +373,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
412 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { | 373 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { |
413 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " | 374 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " |
414 | "set -> send frame\n", tx->dev->name, | 375 | "set -> send frame\n", tx->dev->name, |
415 | print_mac(mac, sta->addr)); | 376 | print_mac(mac, sta->sta.addr)); |
416 | } | 377 | } |
417 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 378 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
418 | clear_sta_flags(sta, WLAN_STA_PSPOLL); | 379 | clear_sta_flags(sta, WLAN_STA_PSPOLL); |
@@ -437,7 +398,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
437 | { | 398 | { |
438 | struct ieee80211_key *key; | 399 | struct ieee80211_key *key; |
439 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 400 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
440 | u16 fc = tx->fc; | 401 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
441 | 402 | ||
442 | if (unlikely(tx->skb->do_not_encrypt)) | 403 | if (unlikely(tx->skb->do_not_encrypt)) |
443 | tx->key = NULL; | 404 | tx->key = NULL; |
@@ -454,22 +415,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
454 | tx->key = NULL; | 415 | tx->key = NULL; |
455 | 416 | ||
456 | if (tx->key) { | 417 | if (tx->key) { |
457 | u16 ftype, stype; | ||
458 | |||
459 | tx->key->tx_rx_count++; | 418 | tx->key->tx_rx_count++; |
460 | /* TODO: add threshold stuff again */ | 419 | /* TODO: add threshold stuff again */ |
461 | 420 | ||
462 | switch (tx->key->conf.alg) { | 421 | switch (tx->key->conf.alg) { |
463 | case ALG_WEP: | 422 | case ALG_WEP: |
464 | ftype = fc & IEEE80211_FCTL_FTYPE; | 423 | if (ieee80211_is_auth(hdr->frame_control)) |
465 | stype = fc & IEEE80211_FCTL_STYPE; | ||
466 | |||
467 | if (ftype == IEEE80211_FTYPE_MGMT && | ||
468 | stype == IEEE80211_STYPE_AUTH) | ||
469 | break; | 424 | break; |
470 | case ALG_TKIP: | 425 | case ALG_TKIP: |
471 | case ALG_CCMP: | 426 | case ALG_CCMP: |
472 | if (!WLAN_FC_DATA_PRESENT(fc)) | 427 | if (!ieee80211_is_data_present(hdr->frame_control)) |
473 | tx->key = NULL; | 428 | tx->key = NULL; |
474 | break; | 429 | break; |
475 | } | 430 | } |
@@ -491,20 +446,24 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
491 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 446 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
492 | 447 | ||
493 | if (likely(tx->rate_idx < 0)) { | 448 | if (likely(tx->rate_idx < 0)) { |
494 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | 449 | rate_control_get_rate(tx->sdata, sband, tx->sta, |
450 | tx->skb, &rsel); | ||
451 | if (tx->sta) | ||
452 | tx->sta->last_txrate_idx = rsel.rate_idx; | ||
495 | tx->rate_idx = rsel.rate_idx; | 453 | tx->rate_idx = rsel.rate_idx; |
496 | if (unlikely(rsel.probe_idx >= 0)) { | 454 | if (unlikely(rsel.probe_idx >= 0)) { |
497 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 455 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
498 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; | 456 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; |
499 | info->control.alt_retry_rate_idx = tx->rate_idx; | 457 | info->control.retries[0].rate_idx = tx->rate_idx; |
458 | info->control.retries[0].limit = tx->local->hw.max_altrate_tries; | ||
500 | tx->rate_idx = rsel.probe_idx; | 459 | tx->rate_idx = rsel.probe_idx; |
501 | } else | 460 | } else if (info->control.retries[0].limit == 0) |
502 | info->control.alt_retry_rate_idx = -1; | 461 | info->control.retries[0].rate_idx = -1; |
503 | 462 | ||
504 | if (unlikely(tx->rate_idx < 0)) | 463 | if (unlikely(tx->rate_idx < 0)) |
505 | return TX_DROP; | 464 | return TX_DROP; |
506 | } else | 465 | } else |
507 | info->control.alt_retry_rate_idx = -1; | 466 | info->control.retries[0].rate_idx = -1; |
508 | 467 | ||
509 | if (tx->sdata->bss_conf.use_cts_prot && | 468 | if (tx->sdata->bss_conf.use_cts_prot && |
510 | (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { | 469 | (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { |
@@ -535,7 +494,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
535 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 494 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
536 | 495 | ||
537 | if (tx->sta) | 496 | if (tx->sta) |
538 | info->control.aid = tx->sta->aid; | 497 | info->control.sta = &tx->sta->sta; |
539 | 498 | ||
540 | if (!info->control.retry_limit) { | 499 | if (!info->control.retry_limit) { |
541 | if (!is_multicast_ether_addr(hdr->addr1)) { | 500 | if (!is_multicast_ether_addr(hdr->addr1)) { |
@@ -563,7 +522,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
563 | * frames. | 522 | * frames. |
564 | * TODO: The last fragment could still use multiple retry | 523 | * TODO: The last fragment could still use multiple retry |
565 | * rates. */ | 524 | * rates. */ |
566 | info->control.alt_retry_rate_idx = -1; | 525 | info->control.retries[0].rate_idx = -1; |
567 | } | 526 | } |
568 | 527 | ||
569 | /* Use CTS protection for unicast frames sent using extended rates if | 528 | /* Use CTS protection for unicast frames sent using extended rates if |
@@ -593,7 +552,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
593 | int idx; | 552 | int idx; |
594 | 553 | ||
595 | /* Do not use multiple retry rates when using RTS/CTS */ | 554 | /* Do not use multiple retry rates when using RTS/CTS */ |
596 | info->control.alt_retry_rate_idx = -1; | 555 | info->control.retries[0].rate_idx = -1; |
597 | 556 | ||
598 | /* Use min(data rate, max base rate) as CTS/RTS rate */ | 557 | /* Use min(data rate, max base rate) as CTS/RTS rate */ |
599 | rate = &sband->bitrates[tx->rate_idx]; | 558 | rate = &sband->bitrates[tx->rate_idx]; |
@@ -601,7 +560,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
601 | for (idx = 0; idx < sband->n_bitrates; idx++) { | 560 | for (idx = 0; idx < sband->n_bitrates; idx++) { |
602 | if (sband->bitrates[idx].bitrate > rate->bitrate) | 561 | if (sband->bitrates[idx].bitrate > rate->bitrate) |
603 | continue; | 562 | continue; |
604 | if (tx->sdata->basic_rates & BIT(idx) && | 563 | if (tx->sdata->bss_conf.basic_rates & BIT(idx) && |
605 | (baserate < 0 || | 564 | (baserate < 0 || |
606 | (sband->bitrates[baserate].bitrate | 565 | (sband->bitrates[baserate].bitrate |
607 | < sband->bitrates[idx].bitrate))) | 566 | < sband->bitrates[idx].bitrate))) |
@@ -615,7 +574,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
615 | } | 574 | } |
616 | 575 | ||
617 | if (tx->sta) | 576 | if (tx->sta) |
618 | info->control.aid = tx->sta->aid; | 577 | info->control.sta = &tx->sta->sta; |
619 | 578 | ||
620 | return TX_CONTINUE; | 579 | return TX_CONTINUE; |
621 | } | 580 | } |
@@ -629,7 +588,14 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
629 | u8 *qc; | 588 | u8 *qc; |
630 | int tid; | 589 | int tid; |
631 | 590 | ||
632 | /* only for injected frames */ | 591 | /* |
592 | * Packet injection may want to control the sequence | ||
593 | * number, if we have no matching interface then we | ||
594 | * neither assign one ourselves nor ask the driver to. | ||
595 | */ | ||
596 | if (unlikely(!info->control.vif)) | ||
597 | return TX_CONTINUE; | ||
598 | |||
633 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) | 599 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) |
634 | return TX_CONTINUE; | 600 | return TX_CONTINUE; |
635 | 601 | ||
@@ -854,7 +820,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
854 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 820 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
855 | 821 | ||
856 | skb->do_not_encrypt = 1; | 822 | skb->do_not_encrypt = 1; |
857 | info->flags |= IEEE80211_TX_CTL_INJECTED; | ||
858 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 823 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
859 | 824 | ||
860 | /* | 825 | /* |
@@ -986,7 +951,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
986 | 951 | ||
987 | /* process and remove the injection radiotap header */ | 952 | /* process and remove the injection radiotap header */ |
988 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 953 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
989 | if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) { | 954 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
990 | if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) | 955 | if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) |
991 | return TX_DROP; | 956 | return TX_DROP; |
992 | 957 | ||
@@ -1000,7 +965,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1000 | hdr = (struct ieee80211_hdr *) skb->data; | 965 | hdr = (struct ieee80211_hdr *) skb->data; |
1001 | 966 | ||
1002 | tx->sta = sta_info_get(local, hdr->addr1); | 967 | tx->sta = sta_info_get(local, hdr->addr1); |
1003 | tx->fc = le16_to_cpu(hdr->frame_control); | ||
1004 | 968 | ||
1005 | if (is_multicast_ether_addr(hdr->addr1)) { | 969 | if (is_multicast_ether_addr(hdr->addr1)) { |
1006 | tx->flags &= ~IEEE80211_TX_UNICAST; | 970 | tx->flags &= ~IEEE80211_TX_UNICAST; |
@@ -1025,7 +989,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1025 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) | 989 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1026 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 990 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1027 | 991 | ||
1028 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 992 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1029 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 993 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
1030 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 994 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
1031 | tx->ethertype = (pos[0] << 8) | pos[1]; | 995 | tx->ethertype = (pos[0] << 8) | pos[1]; |
@@ -1038,14 +1002,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1038 | /* | 1002 | /* |
1039 | * NB: @tx is uninitialised when passed in here | 1003 | * NB: @tx is uninitialised when passed in here |
1040 | */ | 1004 | */ |
1041 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1005 | static int ieee80211_tx_prepare(struct ieee80211_local *local, |
1042 | struct sk_buff *skb, | 1006 | struct ieee80211_tx_data *tx, |
1043 | struct net_device *mdev) | 1007 | struct sk_buff *skb) |
1044 | { | 1008 | { |
1045 | struct net_device *dev; | 1009 | struct net_device *dev; |
1046 | 1010 | ||
1047 | dev = dev_get_by_index(&init_net, skb->iif); | 1011 | dev = dev_get_by_index(&init_net, skb->iif); |
1048 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1012 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { |
1049 | dev_put(dev); | 1013 | dev_put(dev); |
1050 | dev = NULL; | 1014 | dev = NULL; |
1051 | } | 1015 | } |
@@ -1068,8 +1032,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1068 | return IEEE80211_TX_AGAIN; | 1032 | return IEEE80211_TX_AGAIN; |
1069 | info = IEEE80211_SKB_CB(skb); | 1033 | info = IEEE80211_SKB_CB(skb); |
1070 | 1034 | ||
1071 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | ||
1072 | "TX to low-level driver", skb); | ||
1073 | ret = local->ops->tx(local_to_hw(local), skb); | 1035 | ret = local->ops->tx(local_to_hw(local), skb); |
1074 | if (ret) | 1036 | if (ret) |
1075 | return IEEE80211_TX_AGAIN; | 1037 | return IEEE80211_TX_AGAIN; |
@@ -1099,9 +1061,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1099 | ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 1061 | ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
1100 | } | 1062 | } |
1101 | 1063 | ||
1102 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | ||
1103 | "TX to low-level driver", | ||
1104 | tx->extra_frag[i]); | ||
1105 | ret = local->ops->tx(local_to_hw(local), | 1064 | ret = local->ops->tx(local_to_hw(local), |
1106 | tx->extra_frag[i]); | 1065 | tx->extra_frag[i]); |
1107 | if (ret) | 1066 | if (ret) |
@@ -1297,20 +1256,26 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1297 | return 0; | 1256 | return 0; |
1298 | } | 1257 | } |
1299 | 1258 | ||
1300 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1259 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) |
1301 | struct net_device *dev) | ||
1302 | { | 1260 | { |
1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
1262 | struct ieee80211_local *local = mpriv->local; | ||
1303 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1263 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1264 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1305 | struct net_device *odev = NULL; | 1265 | struct net_device *odev = NULL; |
1306 | struct ieee80211_sub_if_data *osdata; | 1266 | struct ieee80211_sub_if_data *osdata; |
1307 | int headroom; | 1267 | int headroom; |
1308 | bool may_encrypt; | 1268 | bool may_encrypt; |
1269 | enum { | ||
1270 | NOT_MONITOR, | ||
1271 | FOUND_SDATA, | ||
1272 | UNKNOWN_ADDRESS, | ||
1273 | } monitor_iface = NOT_MONITOR; | ||
1309 | int ret; | 1274 | int ret; |
1310 | 1275 | ||
1311 | if (skb->iif) | 1276 | if (skb->iif) |
1312 | odev = dev_get_by_index(&init_net, skb->iif); | 1277 | odev = dev_get_by_index(&init_net, skb->iif); |
1313 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1278 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { |
1314 | dev_put(odev); | 1279 | dev_put(odev); |
1315 | odev = NULL; | 1280 | odev = NULL; |
1316 | } | 1281 | } |
@@ -1331,15 +1296,55 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1331 | 1296 | ||
1332 | if (ieee80211_vif_is_mesh(&osdata->vif) && | 1297 | if (ieee80211_vif_is_mesh(&osdata->vif) && |
1333 | ieee80211_is_data(hdr->frame_control)) { | 1298 | ieee80211_is_data(hdr->frame_control)) { |
1334 | if (ieee80211_is_data(hdr->frame_control)) { | 1299 | if (is_multicast_ether_addr(hdr->addr3)) |
1335 | if (is_multicast_ether_addr(hdr->addr3)) | 1300 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); |
1336 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | 1301 | else |
1337 | else | 1302 | if (mesh_nexthop_lookup(skb, osdata)) |
1338 | if (mesh_nexthop_lookup(skb, odev)) | 1303 | return 0; |
1339 | return 0; | 1304 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) |
1340 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1305 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, |
1341 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, | 1306 | fwded_frames); |
1342 | fwded_frames); | 1307 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1308 | struct ieee80211_sub_if_data *sdata; | ||
1309 | int hdrlen; | ||
1310 | u16 len_rthdr; | ||
1311 | |||
1312 | info->flags |= IEEE80211_TX_CTL_INJECTED; | ||
1313 | monitor_iface = UNKNOWN_ADDRESS; | ||
1314 | |||
1315 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | ||
1316 | hdr = (struct ieee80211_hdr *)skb->data + len_rthdr; | ||
1317 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1318 | |||
1319 | /* check the header is complete in the frame */ | ||
1320 | if (likely(skb->len >= len_rthdr + hdrlen)) { | ||
1321 | /* | ||
1322 | * We process outgoing injected frames that have a | ||
1323 | * local address we handle as though they are our | ||
1324 | * own frames. | ||
1325 | * This code here isn't entirely correct, the local | ||
1326 | * MAC address is not necessarily enough to find | ||
1327 | * the interface to use; for that proper VLAN/WDS | ||
1328 | * support we will need a different mechanism. | ||
1329 | */ | ||
1330 | |||
1331 | rcu_read_lock(); | ||
1332 | list_for_each_entry_rcu(sdata, &local->interfaces, | ||
1333 | list) { | ||
1334 | if (!netif_running(sdata->dev)) | ||
1335 | continue; | ||
1336 | if (compare_ether_addr(sdata->dev->dev_addr, | ||
1337 | hdr->addr2)) { | ||
1338 | dev_hold(sdata->dev); | ||
1339 | dev_put(odev); | ||
1340 | osdata = sdata; | ||
1341 | odev = osdata->dev; | ||
1342 | skb->iif = sdata->dev->ifindex; | ||
1343 | monitor_iface = FOUND_SDATA; | ||
1344 | break; | ||
1345 | } | ||
1346 | } | ||
1347 | rcu_read_unlock(); | ||
1343 | } | 1348 | } |
1344 | } | 1349 | } |
1345 | 1350 | ||
@@ -1357,7 +1362,12 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1357 | return 0; | 1362 | return 0; |
1358 | } | 1363 | } |
1359 | 1364 | ||
1360 | info->control.vif = &osdata->vif; | 1365 | if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1366 | osdata = container_of(osdata->bss, | ||
1367 | struct ieee80211_sub_if_data, | ||
1368 | u.ap); | ||
1369 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) | ||
1370 | info->control.vif = &osdata->vif; | ||
1361 | ret = ieee80211_tx(odev, skb); | 1371 | ret = ieee80211_tx(odev, skb); |
1362 | dev_put(odev); | 1372 | dev_put(odev); |
1363 | 1373 | ||
@@ -1437,8 +1447,8 @@ fail: | |||
1437 | int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1447 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1438 | struct net_device *dev) | 1448 | struct net_device *dev) |
1439 | { | 1449 | { |
1440 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1450 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1441 | struct ieee80211_sub_if_data *sdata; | 1451 | struct ieee80211_local *local = sdata->local; |
1442 | int ret = 1, head_need; | 1452 | int ret = 1, head_need; |
1443 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1453 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1444 | __le16 fc; | 1454 | __le16 fc; |
@@ -1450,7 +1460,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1450 | struct sta_info *sta; | 1460 | struct sta_info *sta; |
1451 | u32 sta_flags = 0; | 1461 | u32 sta_flags = 0; |
1452 | 1462 | ||
1453 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1454 | if (unlikely(skb->len < ETH_HLEN)) { | 1463 | if (unlikely(skb->len < ETH_HLEN)) { |
1455 | ret = 0; | 1464 | ret = 0; |
1456 | goto fail; | 1465 | goto fail; |
@@ -1465,8 +1474,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1465 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | 1474 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1466 | 1475 | ||
1467 | switch (sdata->vif.type) { | 1476 | switch (sdata->vif.type) { |
1468 | case IEEE80211_IF_TYPE_AP: | 1477 | case NL80211_IFTYPE_AP: |
1469 | case IEEE80211_IF_TYPE_VLAN: | 1478 | case NL80211_IFTYPE_AP_VLAN: |
1470 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1479 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1471 | /* DA BSSID SA */ | 1480 | /* DA BSSID SA */ |
1472 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1481 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1474,7 +1483,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1474 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1483 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1475 | hdrlen = 24; | 1484 | hdrlen = 24; |
1476 | break; | 1485 | break; |
1477 | case IEEE80211_IF_TYPE_WDS: | 1486 | case NL80211_IFTYPE_WDS: |
1478 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1487 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1479 | /* RA TA DA SA */ | 1488 | /* RA TA DA SA */ |
1480 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1489 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
@@ -1484,24 +1493,56 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1484 | hdrlen = 30; | 1493 | hdrlen = 30; |
1485 | break; | 1494 | break; |
1486 | #ifdef CONFIG_MAC80211_MESH | 1495 | #ifdef CONFIG_MAC80211_MESH |
1487 | case IEEE80211_IF_TYPE_MESH_POINT: | 1496 | case NL80211_IFTYPE_MESH_POINT: |
1488 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1497 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1489 | /* RA TA DA SA */ | 1498 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1490 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1491 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1492 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1493 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1494 | if (!sdata->u.sta.mshcfg.dot11MeshTTL) { | ||
1495 | /* Do not send frames with mesh_ttl == 0 */ | 1499 | /* Do not send frames with mesh_ttl == 0 */ |
1496 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 1500 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1497 | ret = 0; | 1501 | ret = 0; |
1498 | goto fail; | 1502 | goto fail; |
1499 | } | 1503 | } |
1500 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1504 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1505 | |||
1506 | if (compare_ether_addr(dev->dev_addr, | ||
1507 | skb->data + ETH_ALEN) == 0) { | ||
1508 | /* RA TA DA SA */ | ||
1509 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1510 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1511 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1512 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1513 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1514 | } else { | ||
1515 | /* packet from other interface */ | ||
1516 | struct mesh_path *mppath; | ||
1517 | |||
1518 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1519 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1520 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1521 | |||
1522 | if (is_multicast_ether_addr(skb->data)) | ||
1523 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1524 | else { | ||
1525 | rcu_read_lock(); | ||
1526 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1527 | if (mppath) | ||
1528 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | ||
1529 | else | ||
1530 | memset(hdr.addr3, 0xff, ETH_ALEN); | ||
1531 | rcu_read_unlock(); | ||
1532 | } | ||
1533 | |||
1534 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1535 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1536 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1537 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1538 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1539 | sdata->u.mesh.mesh_seqnum++; | ||
1540 | meshhdrlen = 18; | ||
1541 | } | ||
1501 | hdrlen = 30; | 1542 | hdrlen = 30; |
1502 | break; | 1543 | break; |
1503 | #endif | 1544 | #endif |
1504 | case IEEE80211_IF_TYPE_STA: | 1545 | case NL80211_IFTYPE_STATION: |
1505 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 1546 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1506 | /* BSSID SA DA */ | 1547 | /* BSSID SA DA */ |
1507 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); | 1548 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); |
@@ -1509,7 +1550,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1509 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1550 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1510 | hdrlen = 24; | 1551 | hdrlen = 24; |
1511 | break; | 1552 | break; |
1512 | case IEEE80211_IF_TYPE_IBSS: | 1553 | case NL80211_IFTYPE_ADHOC: |
1513 | /* DA SA BSSID */ | 1554 | /* DA SA BSSID */ |
1514 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1555 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1515 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1556 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -1588,19 +1629,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1588 | nh_pos -= skip_header_bytes; | 1629 | nh_pos -= skip_header_bytes; |
1589 | h_pos -= skip_header_bytes; | 1630 | h_pos -= skip_header_bytes; |
1590 | 1631 | ||
1591 | /* TODO: implement support for fragments so that there is no need to | ||
1592 | * reallocate and copy payload; it might be enough to support one | ||
1593 | * extra fragment that would be copied in the beginning of the frame | ||
1594 | * data.. anyway, it would be nice to include this into skb structure | ||
1595 | * somehow | ||
1596 | * | ||
1597 | * There are few options for this: | ||
1598 | * use skb->cb as an extra space for 802.11 header | ||
1599 | * allocate new buffer if not enough headroom | ||
1600 | * make sure that there is enough headroom in every skb by increasing | ||
1601 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and | ||
1602 | * alloc_skb() (net/core/skbuff.c) | ||
1603 | */ | ||
1604 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); | 1632 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); |
1605 | 1633 | ||
1606 | /* | 1634 | /* |
@@ -1823,10 +1851,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1823 | struct rate_selection rsel; | 1851 | struct rate_selection rsel; |
1824 | struct beacon_data *beacon; | 1852 | struct beacon_data *beacon; |
1825 | struct ieee80211_supported_band *sband; | 1853 | struct ieee80211_supported_band *sband; |
1826 | struct ieee80211_mgmt *mgmt; | ||
1827 | int *num_beacons; | ||
1828 | enum ieee80211_band band = local->hw.conf.channel->band; | 1854 | enum ieee80211_band band = local->hw.conf.channel->band; |
1829 | u8 *pos; | ||
1830 | 1855 | ||
1831 | sband = local->hw.wiphy->bands[band]; | 1856 | sband = local->hw.wiphy->bands[band]; |
1832 | 1857 | ||
@@ -1835,7 +1860,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1835 | sdata = vif_to_sdata(vif); | 1860 | sdata = vif_to_sdata(vif); |
1836 | bdev = sdata->dev; | 1861 | bdev = sdata->dev; |
1837 | 1862 | ||
1838 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 1863 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1839 | ap = &sdata->u.ap; | 1864 | ap = &sdata->u.ap; |
1840 | beacon = rcu_dereference(ap->beacon); | 1865 | beacon = rcu_dereference(ap->beacon); |
1841 | if (ap && beacon) { | 1866 | if (ap && beacon) { |
@@ -1873,11 +1898,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1873 | if (beacon->tail) | 1898 | if (beacon->tail) |
1874 | memcpy(skb_put(skb, beacon->tail_len), | 1899 | memcpy(skb_put(skb, beacon->tail_len), |
1875 | beacon->tail, beacon->tail_len); | 1900 | beacon->tail, beacon->tail_len); |
1876 | |||
1877 | num_beacons = &ap->num_beacons; | ||
1878 | } else | 1901 | } else |
1879 | goto out; | 1902 | goto out; |
1880 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1903 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1881 | struct ieee80211_hdr *hdr; | 1904 | struct ieee80211_hdr *hdr; |
1882 | ifsta = &sdata->u.sta; | 1905 | ifsta = &sdata->u.sta; |
1883 | 1906 | ||
@@ -1889,11 +1912,13 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1889 | goto out; | 1912 | goto out; |
1890 | 1913 | ||
1891 | hdr = (struct ieee80211_hdr *) skb->data; | 1914 | hdr = (struct ieee80211_hdr *) skb->data; |
1892 | hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 1915 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1893 | IEEE80211_STYPE_BEACON); | 1916 | IEEE80211_STYPE_BEACON); |
1894 | 1917 | ||
1895 | num_beacons = &ifsta->num_beacons; | ||
1896 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1918 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1919 | struct ieee80211_mgmt *mgmt; | ||
1920 | u8 *pos; | ||
1921 | |||
1897 | /* headroom, head length, tail length and maximum TIM length */ | 1922 | /* headroom, head length, tail length and maximum TIM length */ |
1898 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1923 | skb = dev_alloc_skb(local->tx_headroom + 400); |
1899 | if (!skb) | 1924 | if (!skb) |
@@ -1916,9 +1941,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1916 | *pos++ = WLAN_EID_SSID; | 1941 | *pos++ = WLAN_EID_SSID; |
1917 | *pos++ = 0x0; | 1942 | *pos++ = 0x0; |
1918 | 1943 | ||
1919 | mesh_mgmt_ies_add(skb, sdata->dev); | 1944 | mesh_mgmt_ies_add(skb, sdata); |
1920 | |||
1921 | num_beacons = &sdata->u.sta.num_beacons; | ||
1922 | } else { | 1945 | } else { |
1923 | WARN_ON(1); | 1946 | WARN_ON(1); |
1924 | goto out; | 1947 | goto out; |
@@ -1929,7 +1952,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1929 | skb->do_not_encrypt = 1; | 1952 | skb->do_not_encrypt = 1; |
1930 | 1953 | ||
1931 | info->band = band; | 1954 | info->band = band; |
1932 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | 1955 | rate_control_get_rate(sdata, sband, NULL, skb, &rsel); |
1933 | 1956 | ||
1934 | if (unlikely(rsel.rate_idx < 0)) { | 1957 | if (unlikely(rsel.rate_idx < 0)) { |
1935 | if (net_ratelimit()) { | 1958 | if (net_ratelimit()) { |
@@ -1955,7 +1978,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1955 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 1978 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
1956 | info->control.retry_limit = 1; | 1979 | info->control.retry_limit = 1; |
1957 | 1980 | ||
1958 | (*num_beacons)++; | ||
1959 | out: | 1981 | out: |
1960 | rcu_read_unlock(); | 1982 | rcu_read_unlock(); |
1961 | return skb; | 1983 | return skb; |
@@ -2017,7 +2039,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2017 | rcu_read_lock(); | 2039 | rcu_read_lock(); |
2018 | beacon = rcu_dereference(bss->beacon); | 2040 | beacon = rcu_dereference(bss->beacon); |
2019 | 2041 | ||
2020 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head) | 2042 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) |
2021 | goto out; | 2043 | goto out; |
2022 | 2044 | ||
2023 | if (bss->dtim_count != 0) | 2045 | if (bss->dtim_count != 0) |
@@ -2039,7 +2061,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2039 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2061 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2040 | } | 2062 | } |
2041 | 2063 | ||
2042 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) | 2064 | if (!ieee80211_tx_prepare(local, &tx, skb)) |
2043 | break; | 2065 | break; |
2044 | dev_kfree_skb_any(skb); | 2066 | dev_kfree_skb_any(skb); |
2045 | } | 2067 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0d463c80c404..cee4884b9d06 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -43,7 +43,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = | |||
43 | 43 | ||
44 | 44 | ||
45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
46 | enum ieee80211_if_types type) | 46 | enum nl80211_iftype type) |
47 | { | 47 | { |
48 | __le16 fc = hdr->frame_control; | 48 | __le16 fc = hdr->frame_control; |
49 | 49 | ||
@@ -77,10 +77,10 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
77 | 77 | ||
78 | if (ieee80211_is_back_req(fc)) { | 78 | if (ieee80211_is_back_req(fc)) { |
79 | switch (type) { | 79 | switch (type) { |
80 | case IEEE80211_IF_TYPE_STA: | 80 | case NL80211_IFTYPE_STATION: |
81 | return hdr->addr2; | 81 | return hdr->addr2; |
82 | case IEEE80211_IF_TYPE_AP: | 82 | case NL80211_IFTYPE_AP: |
83 | case IEEE80211_IF_TYPE_VLAN: | 83 | case NL80211_IFTYPE_AP_VLAN: |
84 | return hdr->addr1; | 84 | return hdr->addr1; |
85 | default: | 85 | default: |
86 | break; /* fall through to the return */ | 86 | break; /* fall through to the return */ |
@@ -91,45 +91,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
91 | return NULL; | 91 | return NULL; |
92 | } | 92 | } |
93 | 93 | ||
94 | int ieee80211_get_hdrlen(u16 fc) | ||
95 | { | ||
96 | int hdrlen = 24; | ||
97 | |||
98 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
99 | case IEEE80211_FTYPE_DATA: | ||
100 | if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) | ||
101 | hdrlen = 30; /* Addr4 */ | ||
102 | /* | ||
103 | * The QoS Control field is two bytes and its presence is | ||
104 | * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to | ||
105 | * hdrlen if that bit is set. | ||
106 | * This works by masking out the bit and shifting it to | ||
107 | * bit position 1 so the result has the value 0 or 2. | ||
108 | */ | ||
109 | hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) | ||
110 | >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1); | ||
111 | break; | ||
112 | case IEEE80211_FTYPE_CTL: | ||
113 | /* | ||
114 | * ACK and CTS are 10 bytes, all others 16. To see how | ||
115 | * to get this condition consider | ||
116 | * subtype mask: 0b0000000011110000 (0x00F0) | ||
117 | * ACK subtype: 0b0000000011010000 (0x00D0) | ||
118 | * CTS subtype: 0b0000000011000000 (0x00C0) | ||
119 | * bits that matter: ^^^ (0x00E0) | ||
120 | * value of those: 0b0000000011000000 (0x00C0) | ||
121 | */ | ||
122 | if ((fc & 0xE0) == 0xC0) | ||
123 | hdrlen = 10; | ||
124 | else | ||
125 | hdrlen = 16; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | return hdrlen; | ||
130 | } | ||
131 | EXPORT_SYMBOL(ieee80211_get_hdrlen); | ||
132 | |||
133 | unsigned int ieee80211_hdrlen(__le16 fc) | 94 | unsigned int ieee80211_hdrlen(__le16 fc) |
134 | { | 95 | { |
135 | unsigned int hdrlen = 24; | 96 | unsigned int hdrlen = 24; |
@@ -270,16 +231,21 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
270 | struct ieee80211_rate *rate) | 231 | struct ieee80211_rate *rate) |
271 | { | 232 | { |
272 | struct ieee80211_local *local = hw_to_local(hw); | 233 | struct ieee80211_local *local = hw_to_local(hw); |
273 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 234 | struct ieee80211_sub_if_data *sdata; |
274 | u16 dur; | 235 | u16 dur; |
275 | int erp; | 236 | int erp; |
237 | bool short_preamble = false; | ||
276 | 238 | ||
277 | erp = 0; | 239 | erp = 0; |
278 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 240 | if (vif) { |
279 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 241 | sdata = vif_to_sdata(vif); |
242 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
243 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
244 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
245 | } | ||
280 | 246 | ||
281 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, | 247 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, |
282 | sdata->bss_conf.use_short_preamble); | 248 | short_preamble); |
283 | 249 | ||
284 | return cpu_to_le16(dur); | 250 | return cpu_to_le16(dur); |
285 | } | 251 | } |
@@ -291,7 +257,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
291 | { | 257 | { |
292 | struct ieee80211_local *local = hw_to_local(hw); | 258 | struct ieee80211_local *local = hw_to_local(hw); |
293 | struct ieee80211_rate *rate; | 259 | struct ieee80211_rate *rate; |
294 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 260 | struct ieee80211_sub_if_data *sdata; |
295 | bool short_preamble; | 261 | bool short_preamble; |
296 | int erp; | 262 | int erp; |
297 | u16 dur; | 263 | u16 dur; |
@@ -299,13 +265,17 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
299 | 265 | ||
300 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 266 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
301 | 267 | ||
302 | short_preamble = sdata->bss_conf.use_short_preamble; | 268 | short_preamble = false; |
303 | 269 | ||
304 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 270 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
305 | 271 | ||
306 | erp = 0; | 272 | erp = 0; |
307 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 273 | if (vif) { |
308 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 274 | sdata = vif_to_sdata(vif); |
275 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
276 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
277 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
278 | } | ||
309 | 279 | ||
310 | /* CTS duration */ | 280 | /* CTS duration */ |
311 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, | 281 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, |
@@ -328,7 +298,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
328 | { | 298 | { |
329 | struct ieee80211_local *local = hw_to_local(hw); | 299 | struct ieee80211_local *local = hw_to_local(hw); |
330 | struct ieee80211_rate *rate; | 300 | struct ieee80211_rate *rate; |
331 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 301 | struct ieee80211_sub_if_data *sdata; |
332 | bool short_preamble; | 302 | bool short_preamble; |
333 | int erp; | 303 | int erp; |
334 | u16 dur; | 304 | u16 dur; |
@@ -336,12 +306,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
336 | 306 | ||
337 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 307 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
338 | 308 | ||
339 | short_preamble = sdata->bss_conf.use_short_preamble; | 309 | short_preamble = false; |
340 | 310 | ||
341 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 311 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
342 | erp = 0; | 312 | erp = 0; |
343 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 313 | if (vif) { |
344 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 314 | sdata = vif_to_sdata(vif); |
315 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
316 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
317 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
318 | } | ||
345 | 319 | ||
346 | /* Data frame duration */ | 320 | /* Data frame duration */ |
347 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, | 321 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, |
@@ -386,6 +360,13 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) | |||
386 | } | 360 | } |
387 | EXPORT_SYMBOL(ieee80211_stop_queues); | 361 | EXPORT_SYMBOL(ieee80211_stop_queues); |
388 | 362 | ||
363 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | ||
364 | { | ||
365 | struct ieee80211_local *local = hw_to_local(hw); | ||
366 | return __netif_subqueue_stopped(local->mdev, queue); | ||
367 | } | ||
368 | EXPORT_SYMBOL(ieee80211_queue_stopped); | ||
369 | |||
389 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 370 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
390 | { | 371 | { |
391 | int i; | 372 | int i; |
@@ -408,15 +389,16 @@ void ieee80211_iterate_active_interfaces( | |||
408 | 389 | ||
409 | list_for_each_entry(sdata, &local->interfaces, list) { | 390 | list_for_each_entry(sdata, &local->interfaces, list) { |
410 | switch (sdata->vif.type) { | 391 | switch (sdata->vif.type) { |
411 | case IEEE80211_IF_TYPE_INVALID: | 392 | case __NL80211_IFTYPE_AFTER_LAST: |
412 | case IEEE80211_IF_TYPE_MNTR: | 393 | case NL80211_IFTYPE_UNSPECIFIED: |
413 | case IEEE80211_IF_TYPE_VLAN: | 394 | case NL80211_IFTYPE_MONITOR: |
395 | case NL80211_IFTYPE_AP_VLAN: | ||
414 | continue; | 396 | continue; |
415 | case IEEE80211_IF_TYPE_AP: | 397 | case NL80211_IFTYPE_AP: |
416 | case IEEE80211_IF_TYPE_STA: | 398 | case NL80211_IFTYPE_STATION: |
417 | case IEEE80211_IF_TYPE_IBSS: | 399 | case NL80211_IFTYPE_ADHOC: |
418 | case IEEE80211_IF_TYPE_WDS: | 400 | case NL80211_IFTYPE_WDS: |
419 | case IEEE80211_IF_TYPE_MESH_POINT: | 401 | case NL80211_IFTYPE_MESH_POINT: |
420 | break; | 402 | break; |
421 | } | 403 | } |
422 | if (netif_running(sdata->dev)) | 404 | if (netif_running(sdata->dev)) |
@@ -441,15 +423,16 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
441 | 423 | ||
442 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 424 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
443 | switch (sdata->vif.type) { | 425 | switch (sdata->vif.type) { |
444 | case IEEE80211_IF_TYPE_INVALID: | 426 | case __NL80211_IFTYPE_AFTER_LAST: |
445 | case IEEE80211_IF_TYPE_MNTR: | 427 | case NL80211_IFTYPE_UNSPECIFIED: |
446 | case IEEE80211_IF_TYPE_VLAN: | 428 | case NL80211_IFTYPE_MONITOR: |
429 | case NL80211_IFTYPE_AP_VLAN: | ||
447 | continue; | 430 | continue; |
448 | case IEEE80211_IF_TYPE_AP: | 431 | case NL80211_IFTYPE_AP: |
449 | case IEEE80211_IF_TYPE_STA: | 432 | case NL80211_IFTYPE_STATION: |
450 | case IEEE80211_IF_TYPE_IBSS: | 433 | case NL80211_IFTYPE_ADHOC: |
451 | case IEEE80211_IF_TYPE_WDS: | 434 | case NL80211_IFTYPE_WDS: |
452 | case IEEE80211_IF_TYPE_MESH_POINT: | 435 | case NL80211_IFTYPE_MESH_POINT: |
453 | break; | 436 | break; |
454 | } | 437 | } |
455 | if (netif_running(sdata->dev)) | 438 | if (netif_running(sdata->dev)) |
@@ -460,3 +443,243 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
460 | rcu_read_unlock(); | 443 | rcu_read_unlock(); |
461 | } | 444 | } |
462 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 445 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); |
446 | |||
447 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
448 | struct ieee802_11_elems *elems) | ||
449 | { | ||
450 | size_t left = len; | ||
451 | u8 *pos = start; | ||
452 | |||
453 | memset(elems, 0, sizeof(*elems)); | ||
454 | elems->ie_start = start; | ||
455 | elems->total_len = len; | ||
456 | |||
457 | while (left >= 2) { | ||
458 | u8 id, elen; | ||
459 | |||
460 | id = *pos++; | ||
461 | elen = *pos++; | ||
462 | left -= 2; | ||
463 | |||
464 | if (elen > left) | ||
465 | return; | ||
466 | |||
467 | switch (id) { | ||
468 | case WLAN_EID_SSID: | ||
469 | elems->ssid = pos; | ||
470 | elems->ssid_len = elen; | ||
471 | break; | ||
472 | case WLAN_EID_SUPP_RATES: | ||
473 | elems->supp_rates = pos; | ||
474 | elems->supp_rates_len = elen; | ||
475 | break; | ||
476 | case WLAN_EID_FH_PARAMS: | ||
477 | elems->fh_params = pos; | ||
478 | elems->fh_params_len = elen; | ||
479 | break; | ||
480 | case WLAN_EID_DS_PARAMS: | ||
481 | elems->ds_params = pos; | ||
482 | elems->ds_params_len = elen; | ||
483 | break; | ||
484 | case WLAN_EID_CF_PARAMS: | ||
485 | elems->cf_params = pos; | ||
486 | elems->cf_params_len = elen; | ||
487 | break; | ||
488 | case WLAN_EID_TIM: | ||
489 | elems->tim = pos; | ||
490 | elems->tim_len = elen; | ||
491 | break; | ||
492 | case WLAN_EID_IBSS_PARAMS: | ||
493 | elems->ibss_params = pos; | ||
494 | elems->ibss_params_len = elen; | ||
495 | break; | ||
496 | case WLAN_EID_CHALLENGE: | ||
497 | elems->challenge = pos; | ||
498 | elems->challenge_len = elen; | ||
499 | break; | ||
500 | case WLAN_EID_WPA: | ||
501 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
502 | pos[2] == 0xf2) { | ||
503 | /* Microsoft OUI (00:50:F2) */ | ||
504 | if (pos[3] == 1) { | ||
505 | /* OUI Type 1 - WPA IE */ | ||
506 | elems->wpa = pos; | ||
507 | elems->wpa_len = elen; | ||
508 | } else if (elen >= 5 && pos[3] == 2) { | ||
509 | if (pos[4] == 0) { | ||
510 | elems->wmm_info = pos; | ||
511 | elems->wmm_info_len = elen; | ||
512 | } else if (pos[4] == 1) { | ||
513 | elems->wmm_param = pos; | ||
514 | elems->wmm_param_len = elen; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | break; | ||
519 | case WLAN_EID_RSN: | ||
520 | elems->rsn = pos; | ||
521 | elems->rsn_len = elen; | ||
522 | break; | ||
523 | case WLAN_EID_ERP_INFO: | ||
524 | elems->erp_info = pos; | ||
525 | elems->erp_info_len = elen; | ||
526 | break; | ||
527 | case WLAN_EID_EXT_SUPP_RATES: | ||
528 | elems->ext_supp_rates = pos; | ||
529 | elems->ext_supp_rates_len = elen; | ||
530 | break; | ||
531 | case WLAN_EID_HT_CAPABILITY: | ||
532 | if (elen >= sizeof(struct ieee80211_ht_cap)) | ||
533 | elems->ht_cap_elem = (void *)pos; | ||
534 | break; | ||
535 | case WLAN_EID_HT_EXTRA_INFO: | ||
536 | if (elen >= sizeof(struct ieee80211_ht_addt_info)) | ||
537 | elems->ht_info_elem = (void *)pos; | ||
538 | break; | ||
539 | case WLAN_EID_MESH_ID: | ||
540 | elems->mesh_id = pos; | ||
541 | elems->mesh_id_len = elen; | ||
542 | break; | ||
543 | case WLAN_EID_MESH_CONFIG: | ||
544 | elems->mesh_config = pos; | ||
545 | elems->mesh_config_len = elen; | ||
546 | break; | ||
547 | case WLAN_EID_PEER_LINK: | ||
548 | elems->peer_link = pos; | ||
549 | elems->peer_link_len = elen; | ||
550 | break; | ||
551 | case WLAN_EID_PREQ: | ||
552 | elems->preq = pos; | ||
553 | elems->preq_len = elen; | ||
554 | break; | ||
555 | case WLAN_EID_PREP: | ||
556 | elems->prep = pos; | ||
557 | elems->prep_len = elen; | ||
558 | break; | ||
559 | case WLAN_EID_PERR: | ||
560 | elems->perr = pos; | ||
561 | elems->perr_len = elen; | ||
562 | break; | ||
563 | case WLAN_EID_CHANNEL_SWITCH: | ||
564 | elems->ch_switch_elem = pos; | ||
565 | elems->ch_switch_elem_len = elen; | ||
566 | break; | ||
567 | case WLAN_EID_QUIET: | ||
568 | if (!elems->quiet_elem) { | ||
569 | elems->quiet_elem = pos; | ||
570 | elems->quiet_elem_len = elen; | ||
571 | } | ||
572 | elems->num_of_quiet_elem++; | ||
573 | break; | ||
574 | case WLAN_EID_COUNTRY: | ||
575 | elems->country_elem = pos; | ||
576 | elems->country_elem_len = elen; | ||
577 | break; | ||
578 | case WLAN_EID_PWR_CONSTRAINT: | ||
579 | elems->pwr_constr_elem = pos; | ||
580 | elems->pwr_constr_elem_len = elen; | ||
581 | break; | ||
582 | default: | ||
583 | break; | ||
584 | } | ||
585 | |||
586 | left -= elen; | ||
587 | pos += elen; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | ||
592 | { | ||
593 | struct ieee80211_local *local = sdata->local; | ||
594 | struct ieee80211_tx_queue_params qparam; | ||
595 | int i; | ||
596 | |||
597 | if (!local->ops->conf_tx) | ||
598 | return; | ||
599 | |||
600 | memset(&qparam, 0, sizeof(qparam)); | ||
601 | |||
602 | qparam.aifs = 2; | ||
603 | |||
604 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
605 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
606 | qparam.cw_min = 31; | ||
607 | else | ||
608 | qparam.cw_min = 15; | ||
609 | |||
610 | qparam.cw_max = 1023; | ||
611 | qparam.txop = 0; | ||
612 | |||
613 | for (i = 0; i < local_to_hw(local)->queues; i++) | ||
614 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | ||
615 | } | ||
616 | |||
617 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
618 | int encrypt) | ||
619 | { | ||
620 | skb->dev = sdata->local->mdev; | ||
621 | skb_set_mac_header(skb, 0); | ||
622 | skb_set_network_header(skb, 0); | ||
623 | skb_set_transport_header(skb, 0); | ||
624 | |||
625 | skb->iif = sdata->dev->ifindex; | ||
626 | skb->do_not_encrypt = !encrypt; | ||
627 | |||
628 | dev_queue_xmit(skb); | ||
629 | } | ||
630 | |||
631 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | ||
632 | { | ||
633 | int ret = -EINVAL; | ||
634 | struct ieee80211_channel *chan; | ||
635 | struct ieee80211_local *local = sdata->local; | ||
636 | |||
637 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
638 | |||
639 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
640 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) { | ||
642 | printk(KERN_DEBUG "%s: IBSS not allowed on frequency " | ||
643 | "%d MHz\n", sdata->dev->name, chan->center_freq); | ||
644 | return ret; | ||
645 | } | ||
646 | local->oper_channel = chan; | ||
647 | |||
648 | if (local->sw_scanning || local->hw_scanning) | ||
649 | ret = 0; | ||
650 | else | ||
651 | ret = ieee80211_hw_config(local); | ||
652 | |||
653 | rate_control_clear(local); | ||
654 | } | ||
655 | |||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | ||
660 | enum ieee80211_band band) | ||
661 | { | ||
662 | struct ieee80211_supported_band *sband; | ||
663 | struct ieee80211_rate *bitrates; | ||
664 | u64 mandatory_rates; | ||
665 | enum ieee80211_rate_flags mandatory_flag; | ||
666 | int i; | ||
667 | |||
668 | sband = local->hw.wiphy->bands[band]; | ||
669 | if (!sband) { | ||
670 | WARN_ON(1); | ||
671 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
672 | } | ||
673 | |||
674 | if (band == IEEE80211_BAND_2GHZ) | ||
675 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | ||
676 | else | ||
677 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | ||
678 | |||
679 | bitrates = sband->bitrates; | ||
680 | mandatory_rates = 0; | ||
681 | for (i = 0; i < sband->n_bitrates; i++) | ||
682 | if (bitrates[i].flags & mandatory_flag) | ||
683 | mandatory_rates |= BIT(i); | ||
684 | return mandatory_rates; | ||
685 | } | ||
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 5c2bf0a3d4db..f0e2d3ecb5c4 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -228,11 +228,10 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
228 | return -1; | 228 | return -1; |
229 | 229 | ||
230 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 230 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
231 | 231 | if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) | |
232 | if (skb->len < 8 + hdrlen) | ||
233 | return -1; | 232 | return -1; |
234 | 233 | ||
235 | len = skb->len - hdrlen - 8; | 234 | len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; |
236 | 235 | ||
237 | keyidx = skb->data[hdrlen + 3] >> 6; | 236 | keyidx = skb->data[hdrlen + 3] >> 6; |
238 | 237 | ||
@@ -292,9 +291,10 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) | |||
292 | ieee80211_rx_result | 291 | ieee80211_rx_result |
293 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | 292 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) |
294 | { | 293 | { |
295 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && | 294 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
296 | ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || | 295 | |
297 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) | 296 | if (!ieee80211_is_data(hdr->frame_control) && |
297 | !ieee80211_is_auth(hdr->frame_control)) | ||
298 | return RX_CONTINUE; | 298 | return RX_CONTINUE; |
299 | 299 | ||
300 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | 300 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { |
@@ -303,7 +303,7 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | |||
303 | } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { | 303 | } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { |
304 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); | 304 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); |
305 | /* remove ICV */ | 305 | /* remove ICV */ |
306 | skb_trim(rx->skb, rx->skb->len - 4); | 306 | skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); |
307 | } | 307 | } |
308 | 308 | ||
309 | return RX_CONTINUE; | 309 | return RX_CONTINUE; |
@@ -313,9 +313,6 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
313 | { | 313 | { |
314 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 314 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
315 | 315 | ||
316 | info->control.iv_len = WEP_IV_LEN; | ||
317 | info->control.icv_len = WEP_ICV_LEN; | ||
318 | |||
319 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 316 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
320 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) | 317 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) |
321 | return -1; | 318 | return -1; |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 34fa8ed1e784..742f811ca416 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -27,22 +27,19 @@ | |||
27 | #include "aes_ccm.h" | 27 | #include "aes_ccm.h" |
28 | 28 | ||
29 | 29 | ||
30 | static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, | 30 | static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, |
31 | int idx, int alg, int remove, | 31 | int idx, int alg, int remove, |
32 | int set_tx_key, const u8 *_key, | 32 | int set_tx_key, const u8 *_key, |
33 | size_t key_len) | 33 | size_t key_len) |
34 | { | 34 | { |
35 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 35 | struct ieee80211_local *local = sdata->local; |
36 | struct sta_info *sta; | 36 | struct sta_info *sta; |
37 | struct ieee80211_key *key; | 37 | struct ieee80211_key *key; |
38 | struct ieee80211_sub_if_data *sdata; | ||
39 | int err; | 38 | int err; |
40 | 39 | ||
41 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
42 | |||
43 | if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { | 40 | if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { |
44 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", | 41 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", |
45 | dev->name, idx); | 42 | sdata->dev->name, idx); |
46 | return -EINVAL; | 43 | return -EINVAL; |
47 | } | 44 | } |
48 | 45 | ||
@@ -125,13 +122,13 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, | |||
125 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) | 122 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) |
126 | return -EOPNOTSUPP; | 123 | return -EOPNOTSUPP; |
127 | 124 | ||
128 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 125 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
129 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 126 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
130 | int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length); | 127 | int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); |
131 | if (ret) | 128 | if (ret) |
132 | return ret; | 129 | return ret; |
133 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | 130 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; |
134 | ieee80211_sta_req_auth(dev, &sdata->u.sta); | 131 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
135 | return 0; | 132 | return 0; |
136 | } | 133 | } |
137 | 134 | ||
@@ -276,21 +273,21 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, | |||
276 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 273 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
277 | int type; | 274 | int type; |
278 | 275 | ||
279 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 276 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
280 | return -EOPNOTSUPP; | 277 | return -EOPNOTSUPP; |
281 | 278 | ||
282 | switch (*mode) { | 279 | switch (*mode) { |
283 | case IW_MODE_INFRA: | 280 | case IW_MODE_INFRA: |
284 | type = IEEE80211_IF_TYPE_STA; | 281 | type = NL80211_IFTYPE_STATION; |
285 | break; | 282 | break; |
286 | case IW_MODE_ADHOC: | 283 | case IW_MODE_ADHOC: |
287 | type = IEEE80211_IF_TYPE_IBSS; | 284 | type = NL80211_IFTYPE_ADHOC; |
288 | break; | 285 | break; |
289 | case IW_MODE_REPEAT: | 286 | case IW_MODE_REPEAT: |
290 | type = IEEE80211_IF_TYPE_WDS; | 287 | type = NL80211_IFTYPE_WDS; |
291 | break; | 288 | break; |
292 | case IW_MODE_MONITOR: | 289 | case IW_MODE_MONITOR: |
293 | type = IEEE80211_IF_TYPE_MNTR; | 290 | type = NL80211_IFTYPE_MONITOR; |
294 | break; | 291 | break; |
295 | default: | 292 | default: |
296 | return -EINVAL; | 293 | return -EINVAL; |
@@ -308,22 +305,22 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, | |||
308 | 305 | ||
309 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 306 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
310 | switch (sdata->vif.type) { | 307 | switch (sdata->vif.type) { |
311 | case IEEE80211_IF_TYPE_AP: | 308 | case NL80211_IFTYPE_AP: |
312 | *mode = IW_MODE_MASTER; | 309 | *mode = IW_MODE_MASTER; |
313 | break; | 310 | break; |
314 | case IEEE80211_IF_TYPE_STA: | 311 | case NL80211_IFTYPE_STATION: |
315 | *mode = IW_MODE_INFRA; | 312 | *mode = IW_MODE_INFRA; |
316 | break; | 313 | break; |
317 | case IEEE80211_IF_TYPE_IBSS: | 314 | case NL80211_IFTYPE_ADHOC: |
318 | *mode = IW_MODE_ADHOC; | 315 | *mode = IW_MODE_ADHOC; |
319 | break; | 316 | break; |
320 | case IEEE80211_IF_TYPE_MNTR: | 317 | case NL80211_IFTYPE_MONITOR: |
321 | *mode = IW_MODE_MONITOR; | 318 | *mode = IW_MODE_MONITOR; |
322 | break; | 319 | break; |
323 | case IEEE80211_IF_TYPE_WDS: | 320 | case NL80211_IFTYPE_WDS: |
324 | *mode = IW_MODE_REPEAT; | 321 | *mode = IW_MODE_REPEAT; |
325 | break; | 322 | break; |
326 | case IEEE80211_IF_TYPE_VLAN: | 323 | case NL80211_IFTYPE_AP_VLAN: |
327 | *mode = IW_MODE_SECOND; /* FIXME */ | 324 | *mode = IW_MODE_SECOND; /* FIXME */ |
328 | break; | 325 | break; |
329 | default: | 326 | default: |
@@ -333,60 +330,31 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, | |||
333 | return 0; | 330 | return 0; |
334 | } | 331 | } |
335 | 332 | ||
336 | int ieee80211_set_freq(struct net_device *dev, int freqMHz) | ||
337 | { | ||
338 | int ret = -EINVAL; | ||
339 | struct ieee80211_channel *chan; | ||
340 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
341 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
342 | |||
343 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
344 | |||
345 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
346 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | ||
347 | chan->flags & IEEE80211_CHAN_NO_IBSS) { | ||
348 | printk(KERN_DEBUG "%s: IBSS not allowed on frequency " | ||
349 | "%d MHz\n", dev->name, chan->center_freq); | ||
350 | return ret; | ||
351 | } | ||
352 | local->oper_channel = chan; | ||
353 | |||
354 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
355 | ret = 0; | ||
356 | else | ||
357 | ret = ieee80211_hw_config(local); | ||
358 | |||
359 | rate_control_clear(local); | ||
360 | } | ||
361 | |||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, | 333 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, |
366 | struct iw_request_info *info, | 334 | struct iw_request_info *info, |
367 | struct iw_freq *freq, char *extra) | 335 | struct iw_freq *freq, char *extra) |
368 | { | 336 | { |
369 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 337 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
370 | 338 | ||
371 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) | 339 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
372 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; | 340 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; |
373 | 341 | ||
374 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | 342 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ |
375 | if (freq->e == 0) { | 343 | if (freq->e == 0) { |
376 | if (freq->m < 0) { | 344 | if (freq->m < 0) { |
377 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) | 345 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
378 | sdata->u.sta.flags |= | 346 | sdata->u.sta.flags |= |
379 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 347 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
380 | return 0; | 348 | return 0; |
381 | } else | 349 | } else |
382 | return ieee80211_set_freq(dev, | 350 | return ieee80211_set_freq(sdata, |
383 | ieee80211_channel_to_frequency(freq->m)); | 351 | ieee80211_channel_to_frequency(freq->m)); |
384 | } else { | 352 | } else { |
385 | int i, div = 1000000; | 353 | int i, div = 1000000; |
386 | for (i = 0; i < freq->e; i++) | 354 | for (i = 0; i < freq->e; i++) |
387 | div /= 10; | 355 | div /= 10; |
388 | if (div > 0) | 356 | if (div > 0) |
389 | return ieee80211_set_freq(dev, freq->m / div); | 357 | return ieee80211_set_freq(sdata, freq->m / div); |
390 | else | 358 | else |
391 | return -EINVAL; | 359 | return -EINVAL; |
392 | } | 360 | } |
@@ -418,8 +386,8 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
418 | len--; | 386 | len--; |
419 | 387 | ||
420 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 388 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
421 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 389 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
422 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 390 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
423 | int ret; | 391 | int ret; |
424 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { | 392 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { |
425 | if (len > IEEE80211_MAX_SSID_LEN) | 393 | if (len > IEEE80211_MAX_SSID_LEN) |
@@ -432,14 +400,14 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
432 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | 400 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; |
433 | else | 401 | else |
434 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL; | 402 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL; |
435 | ret = ieee80211_sta_set_ssid(dev, ssid, len); | 403 | ret = ieee80211_sta_set_ssid(sdata, ssid, len); |
436 | if (ret) | 404 | if (ret) |
437 | return ret; | 405 | return ret; |
438 | ieee80211_sta_req_auth(dev, &sdata->u.sta); | 406 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
439 | return 0; | 407 | return 0; |
440 | } | 408 | } |
441 | 409 | ||
442 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 410 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
443 | memcpy(sdata->u.ap.ssid, ssid, len); | 411 | memcpy(sdata->u.ap.ssid, ssid, len); |
444 | memset(sdata->u.ap.ssid + len, 0, | 412 | memset(sdata->u.ap.ssid + len, 0, |
445 | IEEE80211_MAX_SSID_LEN - len); | 413 | IEEE80211_MAX_SSID_LEN - len); |
@@ -458,9 +426,9 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
458 | 426 | ||
459 | struct ieee80211_sub_if_data *sdata; | 427 | struct ieee80211_sub_if_data *sdata; |
460 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 428 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
461 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 429 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
462 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 430 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
463 | int res = ieee80211_sta_get_ssid(dev, ssid, &len); | 431 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); |
464 | if (res == 0) { | 432 | if (res == 0) { |
465 | data->length = len; | 433 | data->length = len; |
466 | data->flags = 1; | 434 | data->flags = 1; |
@@ -469,7 +437,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
469 | return res; | 437 | return res; |
470 | } | 438 | } |
471 | 439 | ||
472 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 440 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
473 | len = sdata->u.ap.ssid_len; | 441 | len = sdata->u.ap.ssid_len; |
474 | if (len > IW_ESSID_MAX_SIZE) | 442 | if (len > IW_ESSID_MAX_SIZE) |
475 | len = IW_ESSID_MAX_SIZE; | 443 | len = IW_ESSID_MAX_SIZE; |
@@ -489,8 +457,8 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
489 | struct ieee80211_sub_if_data *sdata; | 457 | struct ieee80211_sub_if_data *sdata; |
490 | 458 | ||
491 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 459 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
492 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 460 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
493 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 461 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
494 | int ret; | 462 | int ret; |
495 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { | 463 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { |
496 | memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data, | 464 | memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data, |
@@ -504,12 +472,12 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
504 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL; | 472 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL; |
505 | else | 473 | else |
506 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | 474 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; |
507 | ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data); | 475 | ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); |
508 | if (ret) | 476 | if (ret) |
509 | return ret; | 477 | return ret; |
510 | ieee80211_sta_req_auth(dev, &sdata->u.sta); | 478 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
511 | return 0; | 479 | return 0; |
512 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { | 480 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
513 | /* | 481 | /* |
514 | * If it is necessary to update the WDS peer address | 482 | * If it is necessary to update the WDS peer address |
515 | * while the interface is running, then we need to do | 483 | * while the interface is running, then we need to do |
@@ -537,10 +505,10 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
537 | struct ieee80211_sub_if_data *sdata; | 505 | struct ieee80211_sub_if_data *sdata; |
538 | 506 | ||
539 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 507 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
540 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 508 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
541 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 509 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
542 | if (sdata->u.sta.state == IEEE80211_ASSOCIATED || | 510 | if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED || |
543 | sdata->u.sta.state == IEEE80211_IBSS_JOINED) { | 511 | sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) { |
544 | ap_addr->sa_family = ARPHRD_ETHER; | 512 | ap_addr->sa_family = ARPHRD_ETHER; |
545 | memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); | 513 | memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); |
546 | return 0; | 514 | return 0; |
@@ -548,7 +516,7 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
548 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | 516 | memset(&ap_addr->sa_data, 0, ETH_ALEN); |
549 | return 0; | 517 | return 0; |
550 | } | 518 | } |
551 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { | 519 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
552 | ap_addr->sa_family = ARPHRD_ETHER; | 520 | ap_addr->sa_family = ARPHRD_ETHER; |
553 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); | 521 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); |
554 | return 0; | 522 | return 0; |
@@ -570,10 +538,10 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, | |||
570 | if (!netif_running(dev)) | 538 | if (!netif_running(dev)) |
571 | return -ENETDOWN; | 539 | return -ENETDOWN; |
572 | 540 | ||
573 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 541 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
574 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 542 | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
575 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT && | 543 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && |
576 | sdata->vif.type != IEEE80211_IF_TYPE_AP) | 544 | sdata->vif.type != NL80211_IFTYPE_AP) |
577 | return -EOPNOTSUPP; | 545 | return -EOPNOTSUPP; |
578 | 546 | ||
579 | /* if SSID was specified explicitly then use that */ | 547 | /* if SSID was specified explicitly then use that */ |
@@ -584,7 +552,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, | |||
584 | ssid_len = req->essid_len; | 552 | ssid_len = req->essid_len; |
585 | } | 553 | } |
586 | 554 | ||
587 | return ieee80211_sta_req_scan(dev, ssid, ssid_len); | 555 | return ieee80211_request_scan(sdata, ssid, ssid_len); |
588 | } | 556 | } |
589 | 557 | ||
590 | 558 | ||
@@ -594,11 +562,14 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
594 | { | 562 | { |
595 | int res; | 563 | int res; |
596 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 564 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
565 | struct ieee80211_sub_if_data *sdata; | ||
566 | |||
567 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
597 | 568 | ||
598 | if (local->sta_sw_scanning || local->sta_hw_scanning) | 569 | if (local->sw_scanning || local->hw_scanning) |
599 | return -EAGAIN; | 570 | return -EAGAIN; |
600 | 571 | ||
601 | res = ieee80211_sta_scan_results(dev, info, extra, data->length); | 572 | res = ieee80211_scan_results(local, info, extra, data->length); |
602 | if (res >= 0) { | 573 | if (res >= 0) { |
603 | data->length = res; | 574 | data->length = res; |
604 | return 0; | 575 | return 0; |
@@ -656,7 +627,7 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, | |||
656 | 627 | ||
657 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 628 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
658 | 629 | ||
659 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 630 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
660 | return -EOPNOTSUPP; | 631 | return -EOPNOTSUPP; |
661 | 632 | ||
662 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 633 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
@@ -665,8 +636,8 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, | |||
665 | 636 | ||
666 | sta = sta_info_get(local, sdata->u.sta.bssid); | 637 | sta = sta_info_get(local, sdata->u.sta.bssid); |
667 | 638 | ||
668 | if (sta && sta->txrate_idx < sband->n_bitrates) | 639 | if (sta && sta->last_txrate_idx < sband->n_bitrates) |
669 | rate->value = sband->bitrates[sta->txrate_idx].bitrate; | 640 | rate->value = sband->bitrates[sta->last_txrate_idx].bitrate; |
670 | else | 641 | else |
671 | rate->value = 0; | 642 | rate->value = 0; |
672 | 643 | ||
@@ -804,7 +775,7 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, | |||
804 | * configure it here */ | 775 | * configure it here */ |
805 | 776 | ||
806 | if (local->ops->set_frag_threshold) | 777 | if (local->ops->set_frag_threshold) |
807 | local->ops->set_frag_threshold( | 778 | return local->ops->set_frag_threshold( |
808 | local_to_hw(local), | 779 | local_to_hw(local), |
809 | local->fragmentation_threshold); | 780 | local->fragmentation_threshold); |
810 | 781 | ||
@@ -887,17 +858,17 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev, | |||
887 | struct iw_mlme *mlme = (struct iw_mlme *) extra; | 858 | struct iw_mlme *mlme = (struct iw_mlme *) extra; |
888 | 859 | ||
889 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 860 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
890 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 861 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
891 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | 862 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
892 | return -EINVAL; | 863 | return -EINVAL; |
893 | 864 | ||
894 | switch (mlme->cmd) { | 865 | switch (mlme->cmd) { |
895 | case IW_MLME_DEAUTH: | 866 | case IW_MLME_DEAUTH: |
896 | /* TODO: mlme->addr.sa_data */ | 867 | /* TODO: mlme->addr.sa_data */ |
897 | return ieee80211_sta_deauthenticate(dev, mlme->reason_code); | 868 | return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); |
898 | case IW_MLME_DISASSOC: | 869 | case IW_MLME_DISASSOC: |
899 | /* TODO: mlme->addr.sa_data */ | 870 | /* TODO: mlme->addr.sa_data */ |
900 | return ieee80211_sta_disassociate(dev, mlme->reason_code); | 871 | return ieee80211_sta_disassociate(sdata, mlme->reason_code); |
901 | default: | 872 | default: |
902 | return -EOPNOTSUPP; | 873 | return -EOPNOTSUPP; |
903 | } | 874 | } |
@@ -938,7 +909,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, | |||
938 | } | 909 | } |
939 | 910 | ||
940 | return ieee80211_set_encryption( | 911 | return ieee80211_set_encryption( |
941 | dev, bcaddr, | 912 | sdata, bcaddr, |
942 | idx, alg, remove, | 913 | idx, alg, remove, |
943 | !sdata->default_key, | 914 | !sdata->default_key, |
944 | keybuf, erq->length); | 915 | keybuf, erq->length); |
@@ -983,7 +954,7 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
983 | erq->length = sdata->keys[idx]->conf.keylen; | 954 | erq->length = sdata->keys[idx]->conf.keylen; |
984 | erq->flags |= IW_ENCODE_ENABLED; | 955 | erq->flags |= IW_ENCODE_ENABLED; |
985 | 956 | ||
986 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 957 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
987 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 958 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
988 | switch (ifsta->auth_alg) { | 959 | switch (ifsta->auth_alg) { |
989 | case WLAN_AUTH_OPEN: | 960 | case WLAN_AUTH_OPEN: |
@@ -1057,7 +1028,7 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, | |||
1057 | sdata->drop_unencrypted = !!data->value; | 1028 | sdata->drop_unencrypted = !!data->value; |
1058 | break; | 1029 | break; |
1059 | case IW_AUTH_PRIVACY_INVOKED: | 1030 | case IW_AUTH_PRIVACY_INVOKED: |
1060 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 1031 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1061 | ret = -EINVAL; | 1032 | ret = -EINVAL; |
1062 | else { | 1033 | else { |
1063 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | 1034 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; |
@@ -1072,8 +1043,8 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, | |||
1072 | } | 1043 | } |
1073 | break; | 1044 | break; |
1074 | case IW_AUTH_80211_AUTH_ALG: | 1045 | case IW_AUTH_80211_AUTH_ALG: |
1075 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1046 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
1076 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 1047 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1077 | sdata->u.sta.auth_algs = data->value; | 1048 | sdata->u.sta.auth_algs = data->value; |
1078 | else | 1049 | else |
1079 | ret = -EOPNOTSUPP; | 1050 | ret = -EOPNOTSUPP; |
@@ -1095,8 +1066,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
1095 | 1066 | ||
1096 | rcu_read_lock(); | 1067 | rcu_read_lock(); |
1097 | 1068 | ||
1098 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1069 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
1099 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 1070 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1100 | sta = sta_info_get(local, sdata->u.sta.bssid); | 1071 | sta = sta_info_get(local, sdata->u.sta.bssid); |
1101 | if (!sta) { | 1072 | if (!sta) { |
1102 | wstats->discard.fragment = 0; | 1073 | wstats->discard.fragment = 0; |
@@ -1126,8 +1097,8 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev, | |||
1126 | 1097 | ||
1127 | switch (data->flags & IW_AUTH_INDEX) { | 1098 | switch (data->flags & IW_AUTH_INDEX) { |
1128 | case IW_AUTH_80211_AUTH_ALG: | 1099 | case IW_AUTH_80211_AUTH_ALG: |
1129 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1100 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
1130 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 1101 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1131 | data->value = sdata->u.sta.auth_algs; | 1102 | data->value = sdata->u.sta.auth_algs; |
1132 | else | 1103 | else |
1133 | ret = -EOPNOTSUPP; | 1104 | ret = -EOPNOTSUPP; |
@@ -1184,7 +1155,7 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, | |||
1184 | } else | 1155 | } else |
1185 | idx--; | 1156 | idx--; |
1186 | 1157 | ||
1187 | return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg, | 1158 | return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, |
1188 | remove, | 1159 | remove, |
1189 | ext->ext_flags & | 1160 | ext->ext_flags & |
1190 | IW_ENCODE_EXT_SET_TX_KEY, | 1161 | IW_ENCODE_EXT_SET_TX_KEY, |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 4310e2f65661..139b5f267b34 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -39,7 +39,7 @@ static unsigned int classify_1d(struct sk_buff *skb) | |||
39 | return skb->priority - 256; | 39 | return skb->priority - 256; |
40 | 40 | ||
41 | switch (skb->protocol) { | 41 | switch (skb->protocol) { |
42 | case __constant_htons(ETH_P_IP): | 42 | case htons(ETH_P_IP): |
43 | dscp = ip_hdr(skb)->tos & 0xfc; | 43 | dscp = ip_hdr(skb)->tos & 0xfc; |
44 | break; | 44 | break; |
45 | 45 | ||
@@ -47,8 +47,6 @@ static unsigned int classify_1d(struct sk_buff *skb) | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | if (dscp & 0x1c) | ||
51 | return 0; | ||
52 | return dscp >> 5; | 50 | return dscp >> 5; |
53 | } | 51 | } |
54 | 52 | ||
@@ -75,9 +73,8 @@ static int wme_downgrade_ac(struct sk_buff *skb) | |||
75 | 73 | ||
76 | 74 | ||
77 | /* Indicate which queue to use. */ | 75 | /* Indicate which queue to use. */ |
78 | static u16 classify80211(struct sk_buff *skb, struct net_device *dev) | 76 | static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) |
79 | { | 77 | { |
80 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
81 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 78 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
82 | 79 | ||
83 | if (!ieee80211_is_data(hdr->frame_control)) { | 80 | if (!ieee80211_is_data(hdr->frame_control)) { |
@@ -115,14 +112,15 @@ static u16 classify80211(struct sk_buff *skb, struct net_device *dev) | |||
115 | 112 | ||
116 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | 113 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) |
117 | { | 114 | { |
115 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
116 | struct ieee80211_local *local = mpriv->local; | ||
118 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 117 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
119 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
120 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 118 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
121 | struct sta_info *sta; | 119 | struct sta_info *sta; |
122 | u16 queue; | 120 | u16 queue; |
123 | u8 tid; | 121 | u8 tid; |
124 | 122 | ||
125 | queue = classify80211(skb, dev); | 123 | queue = classify80211(local, skb); |
126 | if (unlikely(queue >= local->hw.queues)) | 124 | if (unlikely(queue >= local->hw.queues)) |
127 | queue = local->hw.queues - 1; | 125 | queue = local->hw.queues - 1; |
128 | 126 | ||
@@ -212,7 +210,7 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | |||
212 | DECLARE_MAC_BUF(mac); | 210 | DECLARE_MAC_BUF(mac); |
213 | printk(KERN_DEBUG "allocated aggregation queue" | 211 | printk(KERN_DEBUG "allocated aggregation queue" |
214 | " %d tid %d addr %s pool=0x%lX\n", | 212 | " %d tid %d addr %s pool=0x%lX\n", |
215 | i, tid, print_mac(mac, sta->addr), | 213 | i, tid, print_mac(mac, sta->sta.addr), |
216 | local->queue_pool[0]); | 214 | local->queue_pool[0]); |
217 | } | 215 | } |
218 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 216 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 04de28c071a6..bc62f28a4d3d 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * IEEE 802.11 driver (80211.o) - QoS datatypes | ||
3 | * Copyright 2004, Instant802 Networks, Inc. | 2 | * Copyright 2004, Instant802 Networks, Inc. |
4 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
5 | * | 4 | * |
@@ -14,8 +13,6 @@ | |||
14 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
15 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
16 | 15 | ||
17 | #define QOS_CONTROL_LEN 2 | ||
18 | |||
19 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 | 16 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 |
20 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 | 17 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 |
21 | 18 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 2f33df0dcccf..6db649480e8f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -127,7 +127,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
127 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 127 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
128 | return RX_DROP_UNUSABLE; | 128 | return RX_DROP_UNUSABLE; |
129 | 129 | ||
130 | mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx, | 130 | mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, |
131 | (void *) skb->data); | 131 | (void *) skb->data); |
132 | return RX_DROP_UNUSABLE; | 132 | return RX_DROP_UNUSABLE; |
133 | } | 133 | } |
@@ -152,9 +152,6 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
152 | int len, tail; | 152 | int len, tail; |
153 | u8 *pos; | 153 | u8 *pos; |
154 | 154 | ||
155 | info->control.icv_len = TKIP_ICV_LEN; | ||
156 | info->control.iv_len = TKIP_IV_LEN; | ||
157 | |||
158 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 155 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
159 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 156 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
160 | /* hwaccel - with no need for preallocated room for IV/ICV */ | 157 | /* hwaccel - with no need for preallocated room for IV/ICV */ |
@@ -256,7 +253,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
256 | 253 | ||
257 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 254 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
258 | key, skb->data + hdrlen, | 255 | key, skb->data + hdrlen, |
259 | skb->len - hdrlen, rx->sta->addr, | 256 | skb->len - hdrlen, rx->sta->sta.addr, |
260 | hdr->addr1, hwaccel, rx->queue, | 257 | hdr->addr1, hwaccel, rx->queue, |
261 | &rx->tkip_iv32, | 258 | &rx->tkip_iv32, |
262 | &rx->tkip_iv16); | 259 | &rx->tkip_iv16); |
@@ -374,9 +371,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
374 | u8 *pos, *pn; | 371 | u8 *pos, *pn; |
375 | int i; | 372 | int i; |
376 | 373 | ||
377 | info->control.icv_len = CCMP_MIC_LEN; | ||
378 | info->control.iv_len = CCMP_HDR_LEN; | ||
379 | |||
380 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 374 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
381 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 375 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
382 | /* hwaccel - with no need for preallocated room for CCMP " | 376 | /* hwaccel - with no need for preallocated room for CCMP " |