1 /* Marvell Wireless LAN device driver: TDLS handling
3 * Copyright (C) 2014, Marvell International Ltd.
5 * This software file (the "File") is distributed by Marvell International
6 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
7 * (the "License"). You may use, redistribute and/or modify this File in
8 * accordance with the terms and conditions of the License, a copy of which
9 * is available on the worldwide web at
10 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
12 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
15 * this warranty disclaimer.
20 /* This function appends rate TLV to scan config command. */
22 mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
25 u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
26 u16 rates_size, supp_rates_size, ext_rates_size;
28 memset(rates, 0, sizeof(rates));
29 rates_size = mwifiex_get_supported_rates(priv, rates);
31 supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
33 if (skb_tailroom(skb) < rates_size + 4) {
34 dev_err(priv->adapter->dev,
35 "Insuffient space while adding rates\n");
39 pos = skb_put(skb, supp_rates_size + 2);
40 *pos++ = WLAN_EID_SUPP_RATES;
41 *pos++ = supp_rates_size;
42 memcpy(pos, rates, supp_rates_size);
44 if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
45 ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
46 pos = skb_put(skb, ext_rates_size + 2);
47 *pos++ = WLAN_EID_EXT_SUPP_RATES;
48 *pos++ = ext_rates_size;
49 memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
56 static void mwifiex_tdls_add_ext_capab(struct sk_buff *skb)
58 struct ieee_types_extcap *extcap;
60 extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
61 extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
62 extcap->ieee_hdr.len = 8;
63 memset(extcap->ext_capab, 0, 8);
64 extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
67 static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
69 u8 *pos = (void *)skb_put(skb, 3);
71 *pos++ = WLAN_EID_QOS_CAPA;
73 *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
76 static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
77 u8 *peer, u8 action_code, u8 dialog_token,
78 u16 status_code, struct sk_buff *skb)
80 struct ieee80211_tdls_data *tf;
83 struct ieee80211_ht_cap *ht_cap;
86 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
88 tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
89 memcpy(tf->da, peer, ETH_ALEN);
90 memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
91 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
92 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
94 switch (action_code) {
95 case WLAN_TDLS_SETUP_REQUEST:
96 tf->category = WLAN_CATEGORY_TDLS;
97 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
98 skb_put(skb, sizeof(tf->u.setup_req));
99 tf->u.setup_req.dialog_token = dialog_token;
100 tf->u.setup_req.capability = cpu_to_le16(capab);
101 ret = mwifiex_tdls_append_rates_ie(priv, skb);
103 dev_kfree_skb_any(skb);
107 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
108 *pos++ = WLAN_EID_HT_CAPABILITY;
109 *pos++ = sizeof(struct ieee80211_ht_cap);
110 ht_cap = (void *)pos;
111 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
112 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
114 dev_kfree_skb_any(skb);
118 mwifiex_tdls_add_ext_capab(skb);
119 mwifiex_tdls_add_qos_capab(skb);
122 case WLAN_TDLS_SETUP_RESPONSE:
123 tf->category = WLAN_CATEGORY_TDLS;
124 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
125 skb_put(skb, sizeof(tf->u.setup_resp));
126 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
127 tf->u.setup_resp.dialog_token = dialog_token;
128 tf->u.setup_resp.capability = cpu_to_le16(capab);
129 ret = mwifiex_tdls_append_rates_ie(priv, skb);
131 dev_kfree_skb_any(skb);
135 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
136 *pos++ = WLAN_EID_HT_CAPABILITY;
137 *pos++ = sizeof(struct ieee80211_ht_cap);
138 ht_cap = (void *)pos;
139 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
140 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
142 dev_kfree_skb_any(skb);
146 mwifiex_tdls_add_ext_capab(skb);
147 mwifiex_tdls_add_qos_capab(skb);
150 case WLAN_TDLS_SETUP_CONFIRM:
151 tf->category = WLAN_CATEGORY_TDLS;
152 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
153 skb_put(skb, sizeof(tf->u.setup_cfm));
154 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
155 tf->u.setup_cfm.dialog_token = dialog_token;
158 case WLAN_TDLS_TEARDOWN:
159 tf->category = WLAN_CATEGORY_TDLS;
160 tf->action_code = WLAN_TDLS_TEARDOWN;
161 skb_put(skb, sizeof(tf->u.teardown));
162 tf->u.teardown.reason_code = cpu_to_le16(status_code);
165 case WLAN_TDLS_DISCOVERY_REQUEST:
166 tf->category = WLAN_CATEGORY_TDLS;
167 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
168 skb_put(skb, sizeof(tf->u.discover_req));
169 tf->u.discover_req.dialog_token = dialog_token;
172 dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
180 mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
182 struct ieee80211_tdls_lnkie *lnkid;
184 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
185 lnkid->ie_type = WLAN_EID_LINK_ID;
186 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
187 sizeof(struct ieee_types_header);
189 memcpy(lnkid->bssid, bssid, ETH_ALEN);
190 memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
191 memcpy(lnkid->resp_sta, peer, ETH_ALEN);
194 int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
195 u8 *peer, u8 action_code, u8 dialog_token,
196 u16 status_code, const u8 *extra_ies,
197 size_t extra_ies_len)
200 struct mwifiex_txinfo *tx_info;
205 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
206 max(sizeof(struct ieee80211_mgmt),
207 sizeof(struct ieee80211_tdls_data)) +
208 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
209 MWIFIEX_SUPPORTED_RATES +
211 sizeof(struct ieee_types_extcap) +
212 sizeof(struct ieee80211_ht_cap) +
213 sizeof(struct ieee_types_bss_co_2040) +
214 sizeof(struct ieee80211_ht_operation) +
215 sizeof(struct ieee80211_tdls_lnkie) +
218 skb = dev_alloc_skb(skb_len);
220 dev_err(priv->adapter->dev,
221 "allocate skb failed for management frame\n");
224 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
226 switch (action_code) {
227 case WLAN_TDLS_SETUP_REQUEST:
228 case WLAN_TDLS_SETUP_CONFIRM:
229 case WLAN_TDLS_TEARDOWN:
230 case WLAN_TDLS_DISCOVERY_REQUEST:
231 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
232 dialog_token, status_code,
235 dev_kfree_skb_any(skb);
239 memcpy(skb_put(skb, extra_ies_len), extra_ies,
241 mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
244 case WLAN_TDLS_SETUP_RESPONSE:
245 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
246 dialog_token, status_code,
249 dev_kfree_skb_any(skb);
253 memcpy(skb_put(skb, extra_ies_len), extra_ies,
255 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
260 switch (action_code) {
261 case WLAN_TDLS_SETUP_REQUEST:
262 case WLAN_TDLS_SETUP_RESPONSE:
263 skb->priority = MWIFIEX_PRIO_BK;
266 skb->priority = MWIFIEX_PRIO_VI;
270 tx_info = MWIFIEX_SKB_TXCB(skb);
271 tx_info->bss_num = priv->bss_num;
272 tx_info->bss_type = priv->bss_type;
274 do_gettimeofday(&tv);
275 skb->tstamp = timeval_to_ktime(tv);
276 mwifiex_queue_tx_pkt(priv, skb);
282 mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
283 u8 action_code, u8 dialog_token,
284 u16 status_code, struct sk_buff *skb)
286 struct ieee80211_mgmt *mgmt;
287 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
290 struct ieee80211_ht_cap *ht_cap;
293 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
295 mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
298 memcpy(mgmt->da, peer, ETH_ALEN);
299 memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
300 memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
301 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
302 IEEE80211_STYPE_ACTION);
305 pos = skb_put(skb, ETH_ALEN);
307 switch (action_code) {
308 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
309 skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
310 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
311 mgmt->u.action.u.tdls_discover_resp.action_code =
312 WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
313 mgmt->u.action.u.tdls_discover_resp.dialog_token =
315 mgmt->u.action.u.tdls_discover_resp.capability =
317 /* move back for addr4 */
318 memmove(pos + ETH_ALEN, &mgmt->u.action.category,
319 sizeof(mgmt->u.action.u.tdls_discover_resp));
321 memcpy(pos, bc_addr, ETH_ALEN);
323 ret = mwifiex_tdls_append_rates_ie(priv, skb);
325 dev_kfree_skb_any(skb);
329 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
330 *pos++ = WLAN_EID_HT_CAPABILITY;
331 *pos++ = sizeof(struct ieee80211_ht_cap);
332 ht_cap = (void *)pos;
333 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
334 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
336 dev_kfree_skb_any(skb);
340 mwifiex_tdls_add_ext_capab(skb);
341 mwifiex_tdls_add_qos_capab(skb);
344 dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
351 int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
352 u8 *peer, u8 action_code, u8 dialog_token,
353 u16 status_code, const u8 *extra_ies,
354 size_t extra_ies_len)
357 struct mwifiex_txinfo *tx_info;
360 u32 pkt_type, tx_control;
361 u16 pkt_len, skb_len;
363 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
364 max(sizeof(struct ieee80211_mgmt),
365 sizeof(struct ieee80211_tdls_data)) +
366 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
367 MWIFIEX_SUPPORTED_RATES +
368 sizeof(struct ieee_types_extcap) +
369 sizeof(struct ieee80211_ht_cap) +
370 sizeof(struct ieee_types_bss_co_2040) +
371 sizeof(struct ieee80211_ht_operation) +
372 sizeof(struct ieee80211_tdls_lnkie) +
375 ETH_ALEN; /* Address4 */
377 skb = dev_alloc_skb(skb_len);
379 dev_err(priv->adapter->dev,
380 "allocate skb failed for management frame\n");
384 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
386 pkt_type = PKT_TYPE_MGMT;
388 pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
389 memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
390 memcpy(pos, &pkt_type, sizeof(pkt_type));
391 memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
393 if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
394 dialog_token, status_code,
396 dev_kfree_skb_any(skb);
401 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
403 /* the TDLS link IE is always added last we are the responder */
405 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
408 skb->priority = MWIFIEX_PRIO_VI;
410 tx_info = MWIFIEX_SKB_TXCB(skb);
411 tx_info->bss_num = priv->bss_num;
412 tx_info->bss_type = priv->bss_type;
413 tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
415 pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
416 memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
418 do_gettimeofday(&tv);
419 skb->tstamp = timeval_to_ktime(tv);
420 mwifiex_queue_tx_pkt(priv, skb);