Skip to content

Commit c715350

Browse files
Ron Rindjunskydavem330
Ron Rindjunsky
authored andcommitted
mac80211: adding 802.11n IEs handling
This patch presents the ability to parse and compose HT IEs, and to put the IE relevant data inside the mac80211's internal HT structures Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 10816d4 commit c715350

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

net/mac80211/ieee80211_i.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct ieee80211_sta_bss {
8989
size_t rsn_ie_len;
9090
u8 *wmm_ie;
9191
size_t wmm_ie_len;
92+
u8 *ht_ie;
93+
size_t ht_ie_len;
9294
#define IEEE80211_MAX_SUPP_RATES 32
9395
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
9496
size_t supp_rates_len;
@@ -759,7 +761,11 @@ int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
759761
int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
760762
void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes);
761763
void ieee80211_reset_erp_info(struct net_device *dev);
762-
764+
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
765+
struct ieee80211_ht_info *ht_info);
766+
int ieee80211_ht_addt_info_ie_to_ht_bss_info(
767+
struct ieee80211_ht_addt_info *ht_add_info_ie,
768+
struct ieee80211_ht_bss_info *bss_info);
763769
/* ieee80211_iface.c */
764770
int ieee80211_if_add(struct net_device *dev, const char *name,
765771
struct net_device **new_dev, int type);

net/mac80211/ieee80211_sta.c

+87-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ struct ieee802_11_elems {
9090
u8 *ext_supp_rates;
9191
u8 *wmm_info;
9292
u8 *wmm_param;
93-
93+
u8 *ht_cap_elem;
94+
u8 *ht_info_elem;
9495
/* length of them, respectively */
9596
u8 ssid_len;
9697
u8 supp_rates_len;
@@ -106,6 +107,8 @@ struct ieee802_11_elems {
106107
u8 ext_supp_rates_len;
107108
u8 wmm_info_len;
108109
u8 wmm_param_len;
110+
u8 ht_cap_elem_len;
111+
u8 ht_info_elem_len;
109112
};
110113

111114
static void ieee802_11_parse_elems(u8 *start, size_t len,
@@ -190,6 +193,14 @@ static void ieee802_11_parse_elems(u8 *start, size_t len,
190193
elems->ext_supp_rates = pos;
191194
elems->ext_supp_rates_len = elen;
192195
break;
196+
case WLAN_EID_HT_CAPABILITY:
197+
elems->ht_cap_elem = pos;
198+
elems->ht_cap_elem_len = elen;
199+
break;
200+
case WLAN_EID_HT_EXTRA_INFO:
201+
elems->ht_info_elem = pos;
202+
elems->ht_info_elem_len = elen;
203+
break;
193204
default:
194205
break;
195206
}
@@ -332,6 +343,51 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
332343
ieee80211_erp_info_change_notify(dev, changes);
333344
}
334345

346+
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
347+
struct ieee80211_ht_info *ht_info)
348+
{
349+
350+
if (ht_info == NULL)
351+
return -EINVAL;
352+
353+
memset(ht_info, 0, sizeof(*ht_info));
354+
355+
if (ht_cap_ie) {
356+
u8 ampdu_info = ht_cap_ie->ampdu_params_info;
357+
358+
ht_info->ht_supported = 1;
359+
ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
360+
ht_info->ampdu_factor =
361+
ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
362+
ht_info->ampdu_density =
363+
(ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
364+
memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
365+
} else
366+
ht_info->ht_supported = 0;
367+
368+
return 0;
369+
}
370+
371+
int ieee80211_ht_addt_info_ie_to_ht_bss_info(
372+
struct ieee80211_ht_addt_info *ht_add_info_ie,
373+
struct ieee80211_ht_bss_info *bss_info)
374+
{
375+
if (bss_info == NULL)
376+
return -EINVAL;
377+
378+
memset(bss_info, 0, sizeof(*bss_info));
379+
380+
if (ht_add_info_ie) {
381+
u16 op_mode;
382+
op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
383+
384+
bss_info->primary_channel = ht_add_info_ie->control_chan;
385+
bss_info->bss_cap = ht_add_info_ie->ht_param;
386+
bss_info->bss_op_mode = (u8)(op_mode & 0xff);
387+
}
388+
389+
return 0;
390+
}
335391

336392
static void ieee80211_sta_send_associnfo(struct net_device *dev,
337393
struct ieee80211_if_sta *ifsta)
@@ -630,6 +686,19 @@ static void ieee80211_send_assoc(struct net_device *dev,
630686
*pos++ = 1; /* WME ver */
631687
*pos++ = 0;
632688
}
689+
/* wmm support is a must to HT */
690+
if (wmm && mode->ht_info.ht_supported) {
691+
__le16 tmp = cpu_to_le16(mode->ht_info.cap);
692+
pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
693+
*pos++ = WLAN_EID_HT_CAPABILITY;
694+
*pos++ = sizeof(struct ieee80211_ht_cap);
695+
memset(pos, 0, sizeof(struct ieee80211_ht_cap));
696+
memcpy(pos, &tmp, sizeof(u16));
697+
pos += sizeof(u16);
698+
*pos++ = (mode->ht_info.ampdu_factor |
699+
(mode->ht_info.ampdu_density << 2));
700+
memcpy(pos, mode->ht_info.supp_mcs_set, 16);
701+
}
633702

634703
kfree(ifsta->assocreq_ies);
635704
ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
@@ -1380,6 +1449,7 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
13801449
kfree(bss->wpa_ie);
13811450
kfree(bss->rsn_ie);
13821451
kfree(bss->wmm_ie);
1452+
kfree(bss->ht_ie);
13831453
kfree(bss);
13841454
}
13851455

@@ -1637,7 +1707,22 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
16371707
bss->wmm_ie = NULL;
16381708
bss->wmm_ie_len = 0;
16391709
}
1640-
1710+
if (elems.ht_cap_elem &&
1711+
(!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
1712+
memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
1713+
kfree(bss->ht_ie);
1714+
bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
1715+
if (bss->ht_ie) {
1716+
memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
1717+
elems.ht_cap_elem_len + 2);
1718+
bss->ht_ie_len = elems.ht_cap_elem_len + 2;
1719+
} else
1720+
bss->ht_ie_len = 0;
1721+
} else if (!elems.ht_cap_elem && bss->ht_ie) {
1722+
kfree(bss->ht_ie);
1723+
bss->ht_ie = NULL;
1724+
bss->ht_ie_len = 0;
1725+
}
16411726

16421727
bss->hw_mode = rx_status->phymode;
16431728
bss->freq = rx_status->freq;

0 commit comments

Comments
 (0)