mesh: Enable mesh HT mode
Add a new option "mesh_ht_mode" that specifies the HT mode for the mesh, with this option on, mesh beacons, actions frames, and probe responses with include the appropriate HT information elements. [original implementation by Chun-Yeow Yeoh <yeohchunyeow@gmail.com>] [some fixes by Masashi Honma <masashi.honma@gmail.com>] Signed-off-by: Ashok Nagarajan <ashok.dragon@gmail.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: Jason Mobarak <x@jason.mobarak.name>
This commit is contained in:
parent
c596f3f083
commit
5cfb672dde
10 changed files with 171 additions and 20 deletions
|
@ -308,6 +308,17 @@ enum wpa_ctrl_req_type {
|
|||
/* Maximum number of EAP methods to store for EAP server user information */
|
||||
#define EAP_MAX_METHODS 8
|
||||
|
||||
/**
|
||||
* enum ht_mode - channel width and offset
|
||||
*/
|
||||
enum ht_mode {
|
||||
CHAN_UNDEFINED = 0,
|
||||
CHAN_NO_HT,
|
||||
CHAN_HT20,
|
||||
CHAN_HT40PLUS,
|
||||
CHAN_HT40MINUS,
|
||||
};
|
||||
|
||||
enum mesh_plink_state {
|
||||
PLINK_LISTEN = 1,
|
||||
PLINK_OPEN_SENT,
|
||||
|
|
|
@ -945,6 +945,7 @@ struct wpa_driver_mesh_join_params {
|
|||
const u8 *ies;
|
||||
int ie_len;
|
||||
int freq;
|
||||
enum ht_mode ht_mode;
|
||||
struct wpa_driver_mesh_bss_params conf;
|
||||
#define WPA_DRIVER_MESH_FLAG_USER_MPM 0x00000001
|
||||
#define WPA_DRIVER_MESH_FLAG_DRIVER_MPM 0x00000002
|
||||
|
|
|
@ -8732,12 +8732,38 @@ wpa_driver_nl80211_join_mesh(void *priv,
|
|||
nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_MESH);
|
||||
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||
/* XXX: need chtype too in case we want HT */
|
||||
if (params->freq) {
|
||||
wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
|
||||
}
|
||||
|
||||
if (params->ht_mode) {
|
||||
unsigned int ht_value;
|
||||
char *ht_mode = "";
|
||||
|
||||
switch (params->ht_mode) {
|
||||
default:
|
||||
case CHAN_NO_HT:
|
||||
ht_value = NL80211_CHAN_NO_HT;
|
||||
ht_mode = "NOHT";
|
||||
break;
|
||||
case CHAN_HT20:
|
||||
ht_value = NL80211_CHAN_HT20;
|
||||
ht_mode = "HT20";
|
||||
break;
|
||||
case CHAN_HT40PLUS:
|
||||
ht_value = NL80211_CHAN_HT40PLUS;
|
||||
ht_mode = "HT40+";
|
||||
break;
|
||||
case CHAN_HT40MINUS:
|
||||
ht_value = NL80211_CHAN_HT40MINUS;
|
||||
ht_mode = "HT40-";
|
||||
break;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, " * ht_mode=%s", ht_mode);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ht_value);
|
||||
}
|
||||
|
||||
if (params->basic_rates) {
|
||||
u8 rates[NL80211_MAX_SUPP_RATES];
|
||||
u8 rates_len = 0;
|
||||
|
|
|
@ -75,24 +75,10 @@ no_vht:
|
|||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
|
||||
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct hostapd_config *conf)
|
||||
void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct hostapd_config *conf)
|
||||
{
|
||||
struct hostapd_bss_config *bss = conf->bss[0];
|
||||
|
||||
conf->driver = wpa_s->driver;
|
||||
|
||||
os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
|
||||
|
||||
conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
|
||||
&conf->channel);
|
||||
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
|
||||
wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
|
||||
ssid->frequency);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: enable HT40 if driver supports it;
|
||||
* drop to 11b if driver does not support 11g */
|
||||
|
||||
|
@ -155,6 +141,28 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct hostapd_config *conf)
|
||||
{
|
||||
struct hostapd_bss_config *bss = conf->bss[0];
|
||||
|
||||
conf->driver = wpa_s->driver;
|
||||
|
||||
os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
|
||||
|
||||
conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
|
||||
&conf->channel);
|
||||
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
|
||||
wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
|
||||
ssid->frequency);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
|
||||
|
|
|
@ -75,4 +75,9 @@ int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
|||
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
|
||||
const struct wpabuf *pw, const u8 *pubkey_hash);
|
||||
|
||||
struct hostapd_config;
|
||||
void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct hostapd_config *conf);
|
||||
|
||||
#endif /* AP_H */
|
||||
|
|
|
@ -1588,6 +1588,66 @@ static char * wpa_config_write_psk_list(const struct parse_data *data,
|
|||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
|
||||
static int wpa_config_parse_mesh_ht_mode(const struct parse_data *data,
|
||||
struct wpa_ssid *ssid, int line,
|
||||
const char *value)
|
||||
{
|
||||
int htval = 0;
|
||||
|
||||
if (os_strcmp(value, "NOHT") == 0)
|
||||
htval = CHAN_NO_HT;
|
||||
else if (os_strcmp(value, "HT20") == 0)
|
||||
htval = CHAN_HT20;
|
||||
else if (os_strcmp(value, "HT40-") == 0)
|
||||
htval = CHAN_HT40MINUS;
|
||||
else if (os_strcmp(value, "HT40+") == 0)
|
||||
htval = CHAN_HT40PLUS;
|
||||
else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: no ht_mode configured.", line);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_MSGDUMP, "mesh_ht_mode: 0x%x", htval);
|
||||
ssid->mesh_ht_mode = htval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_CONFIG_WRITE
|
||||
static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
char *val;
|
||||
|
||||
switch (ssid->mesh_ht_mode) {
|
||||
default:
|
||||
val = NULL;
|
||||
break;
|
||||
case CHAN_NO_HT:
|
||||
val = "NOHT";
|
||||
break;
|
||||
case CHAN_HT20:
|
||||
val = "HT20";
|
||||
break;
|
||||
case CHAN_HT40MINUS:
|
||||
val = "HT40-";
|
||||
break;
|
||||
case CHAN_HT40PLUS:
|
||||
val = "HT40+";
|
||||
break;
|
||||
}
|
||||
return val ? os_strdup(val) : NULL;
|
||||
}
|
||||
|
||||
#endif /* NO_CONFIG_WRITE */
|
||||
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
|
||||
/* Helper macros for network block parser */
|
||||
|
||||
#ifdef OFFSET
|
||||
|
@ -1757,6 +1817,9 @@ static const struct parse_data ssid_fields[] = {
|
|||
{ INT_RANGE(peerkey, 0, 1) },
|
||||
{ INT_RANGE(mixed_cell, 0, 1) },
|
||||
{ INT_RANGE(frequency, 0, 65000) },
|
||||
#ifdef CONFIG_MESH
|
||||
{ FUNC(mesh_ht_mode) },
|
||||
#endif /* CONFIG_MESH */
|
||||
{ INT(wpa_ptk_rekey) },
|
||||
{ STR(bgscan) },
|
||||
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
|
||||
|
@ -2235,6 +2298,9 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
|
|||
ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
|
||||
ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM;
|
||||
#endif /* IEEE8021X_EAPOL */
|
||||
#ifdef CONFIG_MESH
|
||||
ssid->mesh_ht_mode = DEFAULT_MESH_HT_MODE;
|
||||
#endif /* CONFIG_MESH */
|
||||
#ifdef CONFIG_HT_OVERRIDES
|
||||
ssid->disable_ht = DEFAULT_DISABLE_HT;
|
||||
ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
|
||||
|
|
|
@ -743,6 +743,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
|||
INT(update_identifier);
|
||||
#endif /* CONFIG_HS20 */
|
||||
write_int(f, "mac_addr", ssid->mac_addr, -1);
|
||||
STR(mesh_ht_mode);
|
||||
|
||||
#undef STR
|
||||
#undef INT
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define DEFAULT_FRAGMENT_SIZE 1398
|
||||
|
||||
#define DEFAULT_BG_SCAN_PERIOD -1
|
||||
#define DEFAULT_MESH_HT_MODE CHAN_UNDEFINED /* undefined */
|
||||
#define DEFAULT_DISABLE_HT 0
|
||||
#define DEFAULT_DISABLE_HT40 0
|
||||
#define DEFAULT_DISABLE_SGI 0
|
||||
|
@ -403,6 +404,15 @@ struct wpa_ssid {
|
|||
*/
|
||||
int frequency;
|
||||
|
||||
/**
|
||||
* mesh_ht_mode - definition of HT mode in mesh mode
|
||||
*
|
||||
* Use the given HT mode for mesh networks. The driver will
|
||||
* adapt to other stations if neccesary, but advertise the
|
||||
* configured HT mode (HT20/HT40-/HT40+/NOHT).
|
||||
*/
|
||||
int mesh_ht_mode;
|
||||
|
||||
int ht40;
|
||||
|
||||
int vht;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "wpa_supplicant_i.h"
|
||||
#include "driver_i.h"
|
||||
#include "notify.h"
|
||||
#include "ap.h"
|
||||
#include "mesh_mpm.h"
|
||||
#include "mesh_rsn.h"
|
||||
#include "mesh.h"
|
||||
|
@ -241,6 +242,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
|
||||
|
||||
return 0;
|
||||
out_free:
|
||||
wpa_supplicant_mesh_deinit(wpa_s);
|
||||
|
@ -295,6 +298,9 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
|
|||
params.meshid = ssid->ssid;
|
||||
params.meshid_len = ssid->ssid_len;
|
||||
params.freq = ssid->frequency;
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
params.ht_mode = ssid->mesh_ht_mode;
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
|
||||
|
|
|
@ -213,6 +213,9 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
|
|||
struct hostapd_data *bss = ifmsh->bss[0];
|
||||
struct mesh_conf *conf = ifmsh->mconf;
|
||||
u8 supp_rates[2 + 2 + 32];
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
u8 ht_capa_oper[2 + 26 + 2 + 22];
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
u8 *pos, *cat;
|
||||
u8 ie_len, add_plid = 0;
|
||||
int ret;
|
||||
|
@ -243,6 +246,7 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
|
|||
/* capability info */
|
||||
wpabuf_put_le16(buf, ampe ? IEEE80211_CAP_PRIVACY : 0);
|
||||
|
||||
/* aid */
|
||||
if (type == PLINK_CONFIRM)
|
||||
wpabuf_put_le16(buf, sta->peer_lid);
|
||||
|
||||
|
@ -309,7 +313,14 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
|
|||
mesh_rsn_get_pmkid(wpa_s->mesh_rsn, sta,
|
||||
wpabuf_put(buf, PMKID_LEN));
|
||||
|
||||
/* TODO HT IEs */
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if (type != PLINK_CLOSE &&
|
||||
wpa_s->current_ssid->mesh_ht_mode != CHAN_NO_HT) {
|
||||
pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
|
||||
pos = hostapd_eid_ht_operation(bss, pos);
|
||||
wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
|
||||
wpa_msg(wpa_s, MSG_INFO,
|
||||
|
@ -520,6 +531,12 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
|
|||
|
||||
mesh_mpm_init_link(wpa_s, sta);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
copy_sta_ht_capab(data, sta, elems->ht_capabilities,
|
||||
elems->ht_capabilities_len);
|
||||
update_ht_state(data, sta);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
/* insert into driver */
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.supp_rates = sta->supported_rates;
|
||||
|
@ -528,7 +545,7 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
|
|||
params.plink_state = sta->plink_state;
|
||||
params.aid = sta->peer_lid;
|
||||
params.listen_interval = 100;
|
||||
/* TODO: HT capabilities */
|
||||
params.ht_capabilities = sta->ht_capabilities;
|
||||
params.flags |= WPA_STA_WMM;
|
||||
params.flags_mask |= WPA_STA_AUTHENTICATED;
|
||||
if (conf->security == MESH_CONF_SEC_NONE) {
|
||||
|
|
Loading…
Reference in a new issue