implement basic 802.11n support
Add suport to enable 80211n support on the BSS and set station parameters through the "Add Station" procedure. Setting 802.11n radio parameters is rudementary and does not work yet.
This commit is contained in:
@ -721,7 +721,7 @@ static void wifi_wlan_receive_station_mgmt_association_request(struct wifi_wlan*
|
||||
}
|
||||
|
||||
/* Create association response packet */
|
||||
memset(¶ms, 0, sizeof(struct ieee80211_authentication_params));
|
||||
memset(¶ms, 0, sizeof(struct ieee80211_associationresponse_params));
|
||||
memcpy(params.bssid, wlan->address, ETH_ALEN);
|
||||
memcpy(params.station, frame->sa, ETH_ALEN);
|
||||
params.capability = wifi_wlan_check_capability(wlan, wlan->capability);
|
||||
@ -1603,6 +1603,40 @@ static void build_80211_ie(uint8_t radioid, uint8_t wlanid, uint8_t type,
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan AC provided IEs for HT Capabilities and HT Operation */
|
||||
static int ht_opmode_from_ie(uint8_t radioid, uint8_t wlanid,
|
||||
struct capwap_array *ie)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ie)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < ie->count; i++) {
|
||||
struct ieee80211_ht_operation *ht_oper;
|
||||
struct capwap_80211_ie_element *e =
|
||||
*(struct capwap_80211_ie_element **)capwap_array_get_item_pointer(ie, i);
|
||||
|
||||
log_printf(LOG_DEBUG, "HT Mode WIFI 802.11: IE: %d:%d %02x (%p)",
|
||||
radioid, wlanid, e->flags, &e->flags);
|
||||
|
||||
if (e->radioid != radioid ||
|
||||
e->wlanid != wlanid ||
|
||||
!(e->flags & CAPWAP_IE_BEACONS_ASSOCIATED) ||
|
||||
e->ielength < 2)
|
||||
continue;
|
||||
|
||||
ht_oper = (struct ieee80211_ht_operation *)e->ie;
|
||||
log_printf(LOG_DEBUG, "HT Mode WIFI 802.11: IE: %02d (%p)",
|
||||
ht_oper->id, ht_oper);
|
||||
if (ht_oper->id == IEEE80211_IE_HT_OPERATION)
|
||||
return __le16_to_cpu(ht_oper->operation_mode);
|
||||
}
|
||||
|
||||
log_printf(LOG_DEBUG, "WIFI 802.11: No HT Operation IE present");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params) {
|
||||
int result;
|
||||
@ -1625,6 +1659,9 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
|
||||
wlan->tunnelmode = params->tunnelmode;
|
||||
wlan->radioid = params->radioid;
|
||||
wlan->wlanid = params->wlanid;
|
||||
wlan->ht_opmode = ht_opmode_from_ie(wlan->radioid, wlan->wlanid,
|
||||
params->ie);
|
||||
log_printf(LOG_DEBUG, "WIFI 802.11: HT OpMode: %04x", wlan->ht_opmode);
|
||||
|
||||
build_80211_ie(wlan->radioid, wlan->wlanid,
|
||||
CAPWAP_IE_BEACONS_ASSOCIATED,
|
||||
@ -1855,8 +1892,13 @@ int wifi_station_authorize(struct wifi_wlan* wlan, struct station_add_params* pa
|
||||
|
||||
/* Station is authorized only after Authentication and Association */
|
||||
station->flags |= WIFI_STATION_FLAGS_AUTHORIZED;
|
||||
if (!(station->flags & WIFI_STATION_FLAGS_AUTHENTICATED) || !(station->flags & WIFI_STATION_FLAGS_ASSOCIATE)) {
|
||||
if (!(station->flags & WIFI_STATION_FLAGS_AUTHENTICATED) ||
|
||||
!(station->flags & WIFI_STATION_FLAGS_ASSOCIATE))
|
||||
return 0;
|
||||
|
||||
if (params->ht_cap) {
|
||||
memcpy(&station->ht_cap, params->ht_cap, sizeof(station->ht_cap));
|
||||
station->flags |= WIFI_STATION_FLAGS_HT_CAP;
|
||||
}
|
||||
|
||||
/* Station authorized */
|
||||
|
@ -124,6 +124,7 @@ struct wlan_send_frame_params {
|
||||
/* */
|
||||
struct station_add_params {
|
||||
uint8_t* address;
|
||||
struct ieee80211_ht_cap *ht_cap;
|
||||
};
|
||||
|
||||
/* Interface capability */
|
||||
@ -151,6 +152,8 @@ struct wifi_band_capability {
|
||||
unsigned long band;
|
||||
|
||||
unsigned long htcapability;
|
||||
uint8_t a_mpdu_params;
|
||||
uint8_t mcs_set[16];
|
||||
|
||||
struct capwap_array* freq;
|
||||
struct capwap_array* rate;
|
||||
@ -300,6 +303,7 @@ struct wifi_wlan {
|
||||
char ssid[IEEE80211_SSID_MAX_LENGTH + 1];
|
||||
uint8_t ssid_hidden;
|
||||
uint16_t capability;
|
||||
int ht_opmode;
|
||||
|
||||
/* Tunnel */
|
||||
uint8_t macmode;
|
||||
@ -321,13 +325,14 @@ struct wifi_wlan {
|
||||
};
|
||||
|
||||
/* Station handle */
|
||||
#define WIFI_STATION_FLAGS_AUTHENTICATED 0x00000001
|
||||
#define WIFI_STATION_FLAGS_ASSOCIATE 0x00000002
|
||||
#define WIFI_STATION_FLAGS_NON_ERP 0x00000004
|
||||
#define WIFI_STATION_FLAGS_AUTHENTICATED 0x00000001
|
||||
#define WIFI_STATION_FLAGS_ASSOCIATE 0x00000002
|
||||
#define WIFI_STATION_FLAGS_NON_ERP 0x00000004
|
||||
#define WIFI_STATION_FLAGS_NO_SHORT_SLOT_TIME 0x00000008
|
||||
#define WIFI_STATION_FLAGS_NO_SHORT_PREAMBLE 0x00000010
|
||||
#define WIFI_STATION_FLAGS_WMM 0x00000020
|
||||
#define WIFI_STATION_FLAGS_AUTHORIZED 0x00000040
|
||||
#define WIFI_STATION_FLAGS_WMM 0x00000020
|
||||
#define WIFI_STATION_FLAGS_AUTHORIZED 0x00000040
|
||||
#define WIFI_STATION_FLAGS_HT_CAP 0x00000080
|
||||
|
||||
/* */
|
||||
#define WIFI_STATION_TIMEOUT_ASSOCIATION_COMPLETE 30000
|
||||
@ -364,6 +369,8 @@ struct wifi_station {
|
||||
uint16_t authalgorithm;
|
||||
|
||||
uint8_t qosinfo;
|
||||
|
||||
struct ieee80211_ht_cap ht_cap;
|
||||
};
|
||||
|
||||
/* */
|
||||
|
@ -762,6 +762,11 @@ static int nl80211_wlan_setbeacon(struct wifi_wlan* wlan) {
|
||||
nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, wlan->device->basicratescount, wlan->device->basicrates);
|
||||
}
|
||||
|
||||
if (wlan->ht_opmode >= 0) {
|
||||
log_printf(LOG_DEBUG, "nl80211: h_opmode=%04x", wlan->ht_opmode);
|
||||
nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, wlan->ht_opmode);
|
||||
}
|
||||
|
||||
/* */
|
||||
result = nl80211_send_and_recv_msg(wlanhandle->devicehandle->globalhandle, msg, NULL, NULL);
|
||||
if (!result) {
|
||||
@ -1036,6 +1041,14 @@ int nl80211_station_authorize(struct wifi_wlan* wlan, struct wifi_station* stati
|
||||
|
||||
/* */
|
||||
wlanhandle = (struct nl80211_wlan_handle*)wlan->handle;
|
||||
|
||||
log_printf(LOG_DEBUG, "nl80211: Add STA " MACSTR, MAC2STR(station->address));
|
||||
log_hexdump(LOG_DEBUG, " * supported rates",
|
||||
station->supportedrates, station->supportedratescount);
|
||||
log_printf(LOG_DEBUG, " * aid=%u", station->aid);
|
||||
log_printf(LOG_DEBUG, " * listen_interval=%u", station->listeninterval);
|
||||
log_printf(LOG_DEBUG, " * capability=0x%x", station->capability);
|
||||
|
||||
genlmsg_put(msg, 0, 0, wlanhandle->devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_NEW_STATION, 0);
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlan->virtindex);
|
||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, station->address);
|
||||
@ -1066,6 +1079,13 @@ int nl80211_station_authorize(struct wifi_wlan* wlan, struct wifi_station* stati
|
||||
nla_nest_end(msg, wme);
|
||||
}
|
||||
|
||||
if (station->flags & WIFI_STATION_FLAGS_HT_CAP) {
|
||||
log_hexdump(LOG_DEBUG, " * ht_capabilities",
|
||||
(uint8_t *)&station->ht_cap, sizeof(station->ht_cap));
|
||||
nla_put(msg, NL80211_ATTR_HT_CAPABILITY,
|
||||
sizeof(station->ht_cap), &station->ht_cap);
|
||||
}
|
||||
|
||||
/* */
|
||||
result = nl80211_send_and_recv_msg(wlanhandle->devicehandle->globalhandle, msg, NULL, NULL);
|
||||
if (result) {
|
||||
@ -1391,6 +1411,18 @@ static int cb_get_phydevice_capability(struct nl_msg* msg, void* data) {
|
||||
capability->radiotype |= CAPWAP_RADIO_TYPE_80211N;
|
||||
}
|
||||
|
||||
if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR])
|
||||
bandcap->a_mpdu_params |= nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) & 0x03;
|
||||
|
||||
if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY])
|
||||
bandcap->a_mpdu_params |= nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) << 2;
|
||||
|
||||
|
||||
if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&
|
||||
nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) >= 16) {
|
||||
memcpy(bandcap->mcs_set, nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]), 16);
|
||||
}
|
||||
|
||||
/* Frequency */
|
||||
if (tb_band[NL80211_BAND_ATTR_FREQS]) {
|
||||
struct nlattr* nl_freq;
|
||||
|
285
src/wtp/wtp.c
285
src/wtp/wtp.c
@ -200,6 +200,84 @@ static int wtp_parsing_radio_qos_configuration(config_setting_t *elem, const cha
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int wtp_parsing_radio_80211n_cfg(config_setting_t *elem,
|
||||
struct wtp_radio *radio)
|
||||
{
|
||||
config_setting_t* sect;
|
||||
int bool;
|
||||
LIBCONFIG_LOOKUP_INT_ARG intval;
|
||||
|
||||
sect = config_setting_get_member(elem, "ieee80211n");
|
||||
if (!sect) {
|
||||
capwap_logging_error("application.radio.ieee80211n not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
radio->n_radio_cfg.radioid = radio->radioid;
|
||||
|
||||
if (config_setting_lookup_bool(sect, "a-msdu", &bool) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.a-msdu not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
if (bool)
|
||||
radio->n_radio_cfg.flags |= CAPWAP_80211N_RADIO_CONF_A_MSDU;
|
||||
|
||||
if (config_setting_lookup_bool(sect, "a-mpdu", &bool) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.a-mpdu not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
if (bool)
|
||||
radio->n_radio_cfg.flags |= CAPWAP_80211N_RADIO_CONF_A_MPDU;
|
||||
|
||||
if (config_setting_lookup_bool(sect, "require-ht", &bool) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.require-ht not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
if (bool)
|
||||
radio->n_radio_cfg.flags |= CAPWAP_80211N_RADIO_CONF_11N_ONLY;
|
||||
|
||||
if (config_setting_lookup_bool(sect, "short-gi", &bool) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.short-gi not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
if (bool)
|
||||
radio->n_radio_cfg.flags |= CAPWAP_80211N_RADIO_CONF_SHORT_GUARD_INTERVAL;
|
||||
|
||||
if (config_setting_lookup_bool(sect, "ht40", &bool) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.ht40 not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
if (!bool)
|
||||
radio->n_radio_cfg.flags |= CAPWAP_80211N_RADIO_CONF_20MHZ_BANDWITH;
|
||||
|
||||
if (config_setting_lookup_int(sect, "max-sup-mcs", &intval) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.max-sup-mcs not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
radio->n_radio_cfg.maxsupmcs = intval;
|
||||
|
||||
if (config_setting_lookup_int(sect, "max-mand-mcs", &intval) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.max-mand-mcs not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
radio->n_radio_cfg.maxmandmcs = intval;
|
||||
|
||||
if (config_setting_lookup_int(sect, "tx-antenna", &intval) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.tx-antenna not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
radio->n_radio_cfg.txant = intval;
|
||||
|
||||
if (config_setting_lookup_int(sect, "rx-antenna", &intval) != CONFIG_TRUE) {
|
||||
capwap_logging_error("application.radio.ieee80211n.rx-antenna not found or wrong type");
|
||||
return 0;
|
||||
}
|
||||
radio->n_radio_cfg.rxant = intval;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int wtp_parsing_radio_configuration(config_setting_t* configElement, struct wtp_radio* radio) {
|
||||
int i, len, cnt;
|
||||
@ -458,9 +536,121 @@ static int wtp_parsing_radio_configuration(config_setting_t* configElement, stru
|
||||
wtp_parsing_radio_qos_configuration(configSection, "besteffort", &radio->qos.qos[0]) == 0 ||
|
||||
wtp_parsing_radio_qos_configuration(configSection, "background", &radio->qos.qos[1]) == 0)
|
||||
return 0;
|
||||
|
||||
if (radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211N) {
|
||||
if (wtp_parsing_radio_80211n_cfg(configElement, radio) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
static int wtp_parsing_radio_section_configuration(config_setting_t* configSetting)
|
||||
{
|
||||
int i;
|
||||
int configBool;
|
||||
const char* configString;
|
||||
struct wtp_radio* radio;
|
||||
const struct wifi_capability* capability;
|
||||
int count = config_setting_length(configSetting);
|
||||
|
||||
if (g_wtp.binding != CAPWAP_WIRELESS_BINDING_IEEE80211)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!IS_VALID_RADIOID(g_wtp.radios->count + 1)) {
|
||||
capwap_logging_error("Exceeded max number of radio device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
config_setting_t* configElement = config_setting_get_elem(configSetting, i);
|
||||
if (!configElement)
|
||||
continue;
|
||||
|
||||
if (config_setting_lookup_string(configElement, "device", &configString) != CONFIG_TRUE) {
|
||||
capwap_logging_error("Invalid configuration file, element application.radio.device not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*configString && (strlen(configString) >= IFNAMSIZ)) {
|
||||
capwap_logging_error("Invalid configuration file, application.radio.device string length exceeded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create new radio device */
|
||||
radio = wtp_radio_create_phy();
|
||||
strcpy(radio->device, configString);
|
||||
|
||||
if (config_setting_lookup_bool(configElement, "enabled", &configBool) != CONFIG_TRUE
|
||||
|| !configBool)
|
||||
continue;
|
||||
|
||||
/* Retrieve radio capability */
|
||||
if (wtp_parsing_radio_configuration(configElement, radio) == 0) {
|
||||
capwap_logging_error("Invalid configuration file, application.radio");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize radio device */
|
||||
if (config_setting_lookup_string(configElement, "driver", &configString) != CONFIG_TRUE ||
|
||||
!*configString ||
|
||||
(strlen(configString) >= WIFI_DRIVER_NAME_SIZE))
|
||||
continue;
|
||||
|
||||
radio->devicehandle = wifi_device_connect(radio->device, configString);
|
||||
if (!radio->devicehandle) {
|
||||
radio->status = WTP_RADIO_HWFAILURE;
|
||||
capwap_logging_warning("Unable to register radio device: %s - %s", radio->device, configString);
|
||||
}
|
||||
|
||||
radio->status = WTP_RADIO_ENABLED;
|
||||
capwap_logging_info("Register radioid %d with radio device: %s - %s", radio->radioid, radio->device, configString);
|
||||
|
||||
/* Update radio capability with device query */
|
||||
capability = wifi_device_getcapability(radio->devicehandle);
|
||||
if (!capability)
|
||||
continue;
|
||||
|
||||
uint8_t bssid;
|
||||
char wlanname[IFNAMSIZ];
|
||||
struct capwap_list_item* itemwlan;
|
||||
struct wtp_radio_wlanpool* wlanpool;
|
||||
|
||||
/* Create interface */
|
||||
for (bssid = 0; bssid < radio->radioconfig.maxbssid; bssid++) {
|
||||
sprintf(wlanname, "%s%02d.%02d", radio->wlanprefix, (int)radio->radioid, (int)bssid + 1);
|
||||
if (wifi_iface_index(wlanname)) {
|
||||
capwap_logging_error("interface %s already exists", wlanname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
itemwlan = capwap_itemlist_create(sizeof(struct wtp_radio_wlanpool));
|
||||
wlanpool = (struct wtp_radio_wlanpool*)itemwlan->item;
|
||||
wlanpool->radio = radio;
|
||||
wlanpool->wlanhandle = wifi_wlan_create(radio->devicehandle, wlanname);
|
||||
if (!wlanpool->wlanhandle) {
|
||||
capwap_logging_error("Unable to create interface: %s", wlanname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Appent to wlan pool */
|
||||
capwap_logging_debug("Created wlan interface: %s", wlanname);
|
||||
capwap_itemlist_insert_after(radio->wlanpool, NULL, itemwlan);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update radio status */
|
||||
g_wtp.descriptor.maxradios = g_wtp.radios->count;
|
||||
g_wtp.descriptor.radiosinuse = wtp_update_radio_in_use();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Parsing configuration */
|
||||
static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
int i;
|
||||
@ -708,98 +898,9 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
|
||||
/* Set Radio WTP */
|
||||
configSetting = config_lookup(config, "application.radio");
|
||||
if (configSetting != NULL) {
|
||||
struct wtp_radio* radio;
|
||||
const struct wifi_capability* capability;
|
||||
int count = config_setting_length(configSetting);
|
||||
|
||||
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!IS_VALID_RADIOID(g_wtp.radios->count + 1)) {
|
||||
capwap_logging_error("Exceeded max number of radio device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
config_setting_t* configElement = config_setting_get_elem(configSetting, i);
|
||||
if (configElement != NULL) {
|
||||
if (config_setting_lookup_string(configElement, "device", &configString) == CONFIG_TRUE) {
|
||||
if (*configString && (strlen(configString) < IFNAMSIZ)) {
|
||||
/* Create new radio device */
|
||||
radio = wtp_radio_create_phy();
|
||||
strcpy(radio->device, configString);
|
||||
|
||||
if (config_setting_lookup_bool(configElement, "enabled", &configBool) == CONFIG_TRUE) {
|
||||
if (configBool) {
|
||||
/* Retrieve radio capability */
|
||||
if (wtp_parsing_radio_configuration(configElement, radio)) {
|
||||
/* Initialize radio device */
|
||||
if (config_setting_lookup_string(configElement, "driver", &configString) == CONFIG_TRUE) {
|
||||
if (*configString && (strlen(configString) < WIFI_DRIVER_NAME_SIZE)) {
|
||||
radio->devicehandle = wifi_device_connect(radio->device, configString);
|
||||
if (radio->devicehandle) {
|
||||
radio->status = WTP_RADIO_ENABLED;
|
||||
capwap_logging_info("Register radioid %d with radio device: %s - %s", radio->radioid, radio->device, configString);
|
||||
|
||||
/* Update radio capability with device query */
|
||||
capability = wifi_device_getcapability(radio->devicehandle);
|
||||
if (capability) {
|
||||
uint8_t bssid;
|
||||
char wlanname[IFNAMSIZ];
|
||||
struct capwap_list_item* itemwlan;
|
||||
struct wtp_radio_wlanpool* wlanpool;
|
||||
|
||||
/* Create interface */
|
||||
for (bssid = 0; bssid < radio->radioconfig.maxbssid; bssid++) {
|
||||
sprintf(wlanname, "%s%02d.%02d", radio->wlanprefix, (int)radio->radioid, (int)bssid + 1);
|
||||
if (wifi_iface_index(wlanname)) {
|
||||
capwap_logging_error("interface %s already exists", wlanname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
itemwlan = capwap_itemlist_create(sizeof(struct wtp_radio_wlanpool));
|
||||
wlanpool = (struct wtp_radio_wlanpool*)itemwlan->item;
|
||||
wlanpool->radio = radio;
|
||||
wlanpool->wlanhandle = wifi_wlan_create(radio->devicehandle, wlanname);
|
||||
if (!wlanpool->wlanhandle) {
|
||||
capwap_logging_error("Unable to create interface: %s", wlanname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Appent to wlan pool */
|
||||
capwap_logging_debug("Created wlan interface: %s", wlanname);
|
||||
capwap_itemlist_insert_after(radio->wlanpool, NULL, itemwlan);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
radio->status = WTP_RADIO_HWFAILURE;
|
||||
capwap_logging_warning("Unable to register radio device: %s - %s", radio->device, configString);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, application.radio");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, application.radio.device string length exceeded");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, element application.radio.device not found");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update radio status */
|
||||
g_wtp.descriptor.maxradios = g_wtp.radios->count;
|
||||
g_wtp.descriptor.radiosinuse = wtp_update_radio_in_use();
|
||||
}
|
||||
}
|
||||
if (configSetting)
|
||||
if (wtp_parsing_radio_section_configuration(configSetting) == 0)
|
||||
return 0;
|
||||
|
||||
/* Set encryption of WTP */
|
||||
configSetting = config_lookup(config, "application.descriptor.encryption");
|
||||
|
@ -71,6 +71,10 @@ void wtp_send_configure(void) {
|
||||
if (radio->radioid == radio->radioconfig.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_RADIO_CONF, &radio->radioconfig);
|
||||
}
|
||||
|
||||
if (radio->radioid == radio->n_radio_cfg.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211N_RADIO_CONF, &radio->n_radio_cfg);
|
||||
}
|
||||
} else {
|
||||
struct capwap_80211_wtpradioinformation_element element = { (uint8_t)radio->radioid, 0 };
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &element);
|
||||
|
@ -171,7 +171,8 @@ static void wtp_radio_setconfiguration_80211(struct capwap_parsed_packet *packet
|
||||
struct capwap_array *messageelements = (struct capwap_array *)messageelement->data;
|
||||
|
||||
/* Parsing only IEEE 802.11 message element */
|
||||
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id))
|
||||
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id) &&
|
||||
memcmp(&messageelement->id, &CAPWAP_ELEMENT_80211N_RADIO_CONF, sizeof(messageelement->id)) != 0)
|
||||
continue;
|
||||
|
||||
ASSERT(messageelements != NULL);
|
||||
@ -230,7 +231,8 @@ static void wtp_radio_setconfiguration_80211(struct capwap_parsed_packet *packet
|
||||
struct capwap_array *messageelements = (struct capwap_array *)messageelement->data;
|
||||
|
||||
/* Parsing only IEEE 802.11 message element */
|
||||
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id))
|
||||
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id) &&
|
||||
memcmp(&messageelement->id, &CAPWAP_ELEMENT_80211N_RADIO_CONF, sizeof(messageelement->id)) != 0)
|
||||
continue;
|
||||
|
||||
ASSERT(messageelements != NULL);
|
||||
@ -385,6 +387,25 @@ static void wtp_radio_setconfiguration_80211(struct capwap_parsed_packet *packet
|
||||
push_wtp_update_configuration_item(updateitems, WTP_UPDATE_CONFIGURATION, radio);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE:
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
struct capwap_80211n_radioconf_element* radioconfig =
|
||||
*(struct capwap_80211n_radioconf_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
|
||||
radio = wtp_radio_get_phy(radioconfig->radioid);
|
||||
if (!radio)
|
||||
continue;
|
||||
|
||||
memcpy(&radio->radioconfig, radioconfig, sizeof(struct capwap_80211n_radioconf_element));
|
||||
|
||||
/* Pending change radio configuration */
|
||||
#if 0
|
||||
/* TODO: handle 802.11n config */
|
||||
push_wtp_update_configuration_item(updateitems, WTP_UPDATE_80211N_CONFIG, radio);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -707,14 +728,21 @@ uint32_t wtp_radio_delete_wlan(struct capwap_parsed_packet* packet) {
|
||||
uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) {
|
||||
struct capwap_addstation_element* addstation;
|
||||
struct capwap_80211_station_element* station80211;
|
||||
struct capwap_80211n_station_info_element *station80211n;
|
||||
struct wtp_radio* radio;
|
||||
struct wtp_radio_wlan* wlan;
|
||||
struct station_add_params stationparams;
|
||||
struct ieee80211_ht_cap ht_cap;
|
||||
int err;
|
||||
|
||||
/* Get message elements */
|
||||
addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ADDSTATION);
|
||||
station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION);
|
||||
addstation = (struct capwap_addstation_element*)
|
||||
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ADDSTATION);
|
||||
station80211 = (struct capwap_80211_station_element*)
|
||||
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION);
|
||||
station80211n = (struct capwap_80211n_station_info_element *)
|
||||
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211N_STATION_INFO);
|
||||
|
||||
if (!station80211 || (addstation->radioid != station80211->radioid)) {
|
||||
capwap_logging_debug("add_station: error no station or wrong radio");
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
@ -738,6 +766,45 @@ uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) {
|
||||
memset(&stationparams, 0, sizeof(struct station_add_params));
|
||||
stationparams.address = station80211->address;
|
||||
|
||||
log_printf(LOG_DEBUG, "Station 802.11n IE: %p", station80211n);
|
||||
if (station80211n) {
|
||||
uint16_t cap_info;
|
||||
|
||||
if (memcmp(station80211->address, station80211n->address,
|
||||
MACADDRESS_EUI48_LENGTH) != 0) {
|
||||
log_printf(LOG_DEBUG, "add_station: 802.11n Station Information MAC mismatch");
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* build 802.11n settings */
|
||||
memset(&ht_cap, 0, sizeof(ht_cap));
|
||||
|
||||
cap_info = 0;
|
||||
if (station80211n->flags & CAPWAP_80211N_STATION_INFO_40MHZ_BANDWITH)
|
||||
cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
if (station80211n->flags & CAPWAP_80211N_STATION_INFO_SHORT_GUARD_INTERVAL_AT_20MHZ)
|
||||
cap_info |= IEEE80211_HT_CAP_SGI_20;
|
||||
if (station80211n->flags & CAPWAP_80211N_STATION_INFO_SHORT_GUARD_INTERVAL_AT_40MHZ)
|
||||
cap_info |= IEEE80211_HT_CAP_SGI_40;
|
||||
if (station80211n->flags & CAPWAP_80211N_STATION_INFO_BLOCK_ACK_DELAY_MODE)
|
||||
cap_info |= IEEE80211_HT_CAP_DELAY_BA;
|
||||
if (station80211n->flags & CAPWAP_80211N_STATION_INFO_MAX_AMSDU_LENGTH_7935)
|
||||
cap_info |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
cap_info |= ((station80211n->flags & CAPWAP_80211N_STATION_INFO_POWER_SAVE_MODE)
|
||||
>> CAPWAP_80211N_STATION_INFO_POWER_SAVE_MODE_SHIFT)
|
||||
<< IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
|
||||
ht_cap.cap_info = __cpu_to_le16(cap_info);
|
||||
|
||||
ht_cap.ampdu_params_info = (station80211n->maxrxfactor & 0x03) |
|
||||
(station80211n->minstaspaceing & 0x07) << 2;
|
||||
|
||||
ht_cap.mcs.rx_highest = __cpu_to_le16(station80211n->hisuppdatarate);
|
||||
memcpy(&ht_cap.mcs.rx_mask, station80211n->mcsset, sizeof(ht_cap.mcs.rx_mask));
|
||||
|
||||
stationparams.ht_cap = &ht_cap;
|
||||
}
|
||||
|
||||
err = wtp_kmod_add_station(addstation->radioid, station80211->address, station80211->wlanid);
|
||||
if (err < 0) {
|
||||
capwap_logging_debug("add_station: CAPWAP add_station failed with: %d", err);
|
||||
|
@ -31,6 +31,11 @@ struct wtp_radio_wlanpool {
|
||||
struct wtp_radio* radio;
|
||||
};
|
||||
|
||||
struct capwap_80211_ie_element_ht_cap {
|
||||
struct capwap_80211_ie_element ie;
|
||||
struct ieee80211_ie_ht_cap ht_cap;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* */
|
||||
struct wtp_radio {
|
||||
uint8_t radioid;
|
||||
@ -52,8 +57,10 @@ struct wtp_radio {
|
||||
struct capwap_80211_txpower_element txpower;
|
||||
struct capwap_80211_txpowerlevel_element txpowerlevel;
|
||||
struct capwap_80211_wtpradioconf_element radioconfig;
|
||||
struct capwap_80211n_radioconf_element n_radio_cfg;
|
||||
struct capwap_80211_wtpradioinformation_element radioinformation;
|
||||
struct capwap_80211_wtpqos_element qos;
|
||||
struct capwap_80211_ie_element_ht_cap ht_cap;
|
||||
};
|
||||
|
||||
/* */
|
||||
|
Reference in New Issue
Block a user