diff options
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r-- | net/mac80211/mesh_plink.c | 50 |
1 files changed, 36 insertions, 14 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7e57f5d07f6..0140e88a822 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -80,11 +80,15 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) | |||
80 | * on it in the lifecycle management section! | 80 | * on it in the lifecycle management section! |
81 | */ | 81 | */ |
82 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | 82 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, |
83 | u8 *hw_addr, u32 rates) | 83 | u8 *hw_addr, u32 rates, |
84 | struct ieee802_11_elems *elems) | ||
84 | { | 85 | { |
85 | struct ieee80211_local *local = sdata->local; | 86 | struct ieee80211_local *local = sdata->local; |
87 | struct ieee80211_supported_band *sband; | ||
86 | struct sta_info *sta; | 88 | struct sta_info *sta; |
87 | 89 | ||
90 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | ||
91 | |||
88 | if (local->num_sta >= MESH_MAX_PLINKS) | 92 | if (local->num_sta >= MESH_MAX_PLINKS) |
89 | return NULL; | 93 | return NULL; |
90 | 94 | ||
@@ -96,6 +100,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
96 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 100 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); |
97 | set_sta_flag(sta, WLAN_STA_WME); | 101 | set_sta_flag(sta, WLAN_STA_WME); |
98 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 102 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
103 | if (elems->ht_cap_elem) | ||
104 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems->ht_cap_elem, | ||
105 | &sta->sta.ht_cap); | ||
99 | rate_control_rate_init(sta); | 106 | rate_control_rate_init(sta); |
100 | 107 | ||
101 | return sta; | 108 | return sta; |
@@ -153,23 +160,31 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
153 | enum ieee80211_self_protected_actioncode action, | 160 | enum ieee80211_self_protected_actioncode action, |
154 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { | 161 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { |
155 | struct ieee80211_local *local = sdata->local; | 162 | struct ieee80211_local *local = sdata->local; |
156 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | 163 | struct sk_buff *skb; |
157 | sdata->u.mesh.ie_len); | ||
158 | struct ieee80211_mgmt *mgmt; | 164 | struct ieee80211_mgmt *mgmt; |
159 | bool include_plid = false; | 165 | bool include_plid = false; |
160 | int ie_len = 4; | ||
161 | u16 peering_proto = 0; | 166 | u16 peering_proto = 0; |
162 | u8 *pos; | 167 | u8 *pos, ie_len = 4; |
163 | 168 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + | |
169 | sizeof(mgmt->u.action.u.self_prot); | ||
170 | |||
171 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
172 | hdr_len + | ||
173 | 2 + /* capability info */ | ||
174 | 2 + /* AID */ | ||
175 | 2 + 8 + /* supported rates */ | ||
176 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | ||
177 | 2 + sdata->u.mesh.mesh_id_len + | ||
178 | 2 + sizeof(struct ieee80211_meshconf_ie) + | ||
179 | 2 + sizeof(struct ieee80211_ht_cap) + | ||
180 | 2 + sizeof(struct ieee80211_ht_info) + | ||
181 | 2 + 8 + /* peering IE */ | ||
182 | sdata->u.mesh.ie_len); | ||
164 | if (!skb) | 183 | if (!skb) |
165 | return -1; | 184 | return -1; |
166 | skb_reserve(skb, local->hw.extra_tx_headroom); | 185 | skb_reserve(skb, local->hw.extra_tx_headroom); |
167 | /* 25 is the size of the common mgmt part (24) plus the size of the | 186 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
168 | * common action part (1) | 187 | memset(mgmt, 0, hdr_len); |
169 | */ | ||
170 | mgmt = (struct ieee80211_mgmt *) | ||
171 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot)); | ||
172 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot)); | ||
173 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 188 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
174 | IEEE80211_STYPE_ACTION); | 189 | IEEE80211_STYPE_ACTION); |
175 | memcpy(mgmt->da, da, ETH_ALEN); | 190 | memcpy(mgmt->da, da, ETH_ALEN); |
@@ -235,6 +250,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
235 | memcpy(pos, &reason, 2); | 250 | memcpy(pos, &reason, 2); |
236 | pos += 2; | 251 | pos += 2; |
237 | } | 252 | } |
253 | |||
254 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | ||
255 | if (mesh_add_ht_cap_ie(skb, sdata) || | ||
256 | mesh_add_ht_info_ie(skb, sdata)) | ||
257 | return -1; | ||
258 | } | ||
259 | |||
238 | if (mesh_add_vendor_ies(skb, sdata)) | 260 | if (mesh_add_vendor_ies(skb, sdata)) |
239 | return -1; | 261 | return -1; |
240 | 262 | ||
@@ -261,7 +283,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, | |||
261 | elems->ie_start, elems->total_len, | 283 | elems->ie_start, elems->total_len, |
262 | GFP_KERNEL); | 284 | GFP_KERNEL); |
263 | else | 285 | else |
264 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 286 | sta = mesh_plink_alloc(sdata, hw_addr, rates, elems); |
265 | if (!sta) | 287 | if (!sta) |
266 | return; | 288 | return; |
267 | if (sta_info_insert_rcu(sta)) { | 289 | if (sta_info_insert_rcu(sta)) { |
@@ -552,7 +574,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
552 | } | 574 | } |
553 | 575 | ||
554 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); | 576 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); |
555 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); | 577 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems); |
556 | if (!sta) { | 578 | if (!sta) { |
557 | mpl_dbg("Mesh plink error: plink table full\n"); | 579 | mpl_dbg("Mesh plink error: plink table full\n"); |
558 | return; | 580 | return; |