rework bssid handling and stop all used bssids when leaving RUN

(this has been backported from master)
Instead of haing a pool of unsused BSS Id's and a list of active
BSS's (wlans), use a single array and only mark the BSS Id as used
or unused.

When leaving RUN state, release (stop) all used BSS.

Conflicts:
	src/wtp/wtp.c
	src/wtp/wtp_radio.c
This commit is contained in:
Tobias Hintze 2016-03-29 16:49:45 +02:00
parent c2a07804db
commit 04b1f205c5
4 changed files with 109 additions and 104 deletions

View File

@ -746,12 +746,12 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
capability = wifi_device_getcapability(radio->devicehandle); capability = wifi_device_getcapability(radio->devicehandle);
if (capability) { if (capability) {
uint8_t bssid; uint8_t bssid;
char wlanname[IFNAMSIZ];
struct capwap_list_item* itemwlan;
struct wtp_radio_wlanpool* wlanpool;
/* Create interface */ /* Create interface */
for (bssid = 0; bssid < radio->radioconfig.maxbssid; bssid++) { for (bssid = 0; bssid < radio->radioconfig.maxbssid; bssid++) {
char wlanname[IFNAMSIZ];
struct wtp_radio_wlan *wlan;
sprintf(wlanname, "%s%02d.%02d", radio->wlanprefix, (int)radio->radioid, (int)bssid + 1); sprintf(wlanname, "%s%02d.%02d", radio->wlanprefix, (int)radio->radioid, (int)bssid + 1);
if (wifi_iface_index(wlanname)) { if (wifi_iface_index(wlanname)) {
capwap_logging_error("interface %s already exists", wlanname); capwap_logging_error("interface %s already exists", wlanname);
@ -759,18 +759,16 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
} }
/* */ /* */
itemwlan = capwap_itemlist_create(sizeof(struct wtp_radio_wlanpool)); wlan = (struct wtp_radio_wlan *)capwap_array_get_item_pointer(radio->wlan, bssid + 1);
wlanpool = (struct wtp_radio_wlanpool*)itemwlan->item; wlan->in_use = 0;
wlanpool->radio = radio; wlan->radio = radio;
wlanpool->wlanhandle = wifi_wlan_create(radio->devicehandle, wlanname); wlan->wlanhandle = wifi_wlan_create(radio->devicehandle, wlanname);
if (!wlanpool->wlanhandle) { if (!wlan->wlanhandle) {
capwap_logging_error("Unable to create interface: %s", wlanname); capwap_logging_error("Unable to create interface: %s", wlanname);
return 0; return 0;
} }
/* Appent to wlan pool */
capwap_logging_debug("Created wlan interface: %s", wlanname); capwap_logging_debug("Created wlan interface: %s", wlanname);
capwap_itemlist_insert_after(radio->wlanpool, NULL, itemwlan);
} }
} }
} else { } else {

View File

@ -548,6 +548,7 @@ void wtp_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long
void wtp_reset_state(void) void wtp_reset_state(void)
{ {
/* reset WTP state */ /* reset WTP state */
wtp_radio_reset();
wtp_free_reference_last_request(); wtp_free_reference_last_request();
wtp_free_reference_last_response(); wtp_free_reference_last_response();

View File

@ -18,7 +18,11 @@ struct wtp_update_configuration_item {
}; };
/* */ /* */
static int wtp_radio_configure_phy(struct wtp_radio* radio) { static int wtp_radio_configure_phy(struct wtp_radio* radio)
{
if (radio->initialized)
return 0;
/* Default rate set is all supported rate */ /* Default rate set is all supported rate */
if (radio->radioid != radio->rateset.radioid) { if (radio->radioid != radio->rateset.radioid) {
if (radio->radioid != radio->supportedrates.radioid) { if (radio->radioid != radio->supportedrates.radioid) {
@ -32,7 +36,8 @@ static int wtp_radio_configure_phy(struct wtp_radio* radio) {
memcpy(radio->rateset.rateset, radio->supportedrates.supportedrates, CAPWAP_RATESET_MAXLENGTH); memcpy(radio->rateset.rateset, radio->supportedrates.supportedrates, CAPWAP_RATESET_MAXLENGTH);
/* Update rates */ /* Update rates */
if (wifi_device_updaterates(radio->devicehandle, radio->rateset.rateset, radio->rateset.ratesetcount)) { if (wifi_device_updaterates(radio->devicehandle, radio->rateset.rateset,
radio->rateset.ratesetcount)) {
capwap_logging_debug("Config Phy: update rates failed"); capwap_logging_debug("Config Phy: update rates failed");
return -1; return -1;
} }
@ -45,17 +50,22 @@ static int wtp_radio_configure_phy(struct wtp_radio* radio) {
} else if (radio->radioid != radio->radioconfig.radioid) { } else if (radio->radioid != radio->radioconfig.radioid) {
capwap_logging_debug("Config Phy: RC id mismatch"); capwap_logging_debug("Config Phy: RC id mismatch");
return -1; return -1;
} else if ((!radio->directsequencecontrol.radioid && !radio->ofdmcontrol.radioid) || ((radio->directsequencecontrol.radioid == radio->radioid) && (radio->ofdmcontrol.radioid == radio->radioid))) { } else if ((!radio->directsequencecontrol.radioid && !radio->ofdmcontrol.radioid) ||
((radio->directsequencecontrol.radioid == radio->radioid) &&
(radio->ofdmcontrol.radioid == radio->radioid))) {
capwap_logging_debug("Config Phy: DSSS / OFDM mismatch"); capwap_logging_debug("Config Phy: DSSS / OFDM mismatch");
return -1; /* Only one from DSSS and OFDM can select */ return -1; /* Only one from DSSS and OFDM can select */
} else if ((radio->radioid == radio->directsequencecontrol.radioid) && !(radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) { } else if ((radio->radioid == radio->directsequencecontrol.radioid) &&
!(radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) {
capwap_logging_debug("Config Phy: DSSS B/G mismatch"); capwap_logging_debug("Config Phy: DSSS B/G mismatch");
return -1; return -1;
} else if ((radio->radioid == radio->ofdmcontrol.radioid) && !(radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) { } else if ((radio->radioid == radio->ofdmcontrol.radioid) &&
!(radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) {
capwap_logging_debug("Config Phy: OFDM A mismatch"); capwap_logging_debug("Config Phy: OFDM A mismatch");
return -1; return -1;
} }
radio->initialized = 1;
return 0; return 0;
} }
@ -89,43 +99,28 @@ void wtp_radio_init(void) {
} }
/* */ /* */
void wtp_radio_close(void) { void wtp_radio_close(void)
{
int i; int i;
struct capwap_list_item* itemwlan;
ASSERT(g_wtp.radios != NULL); ASSERT(g_wtp.radios != NULL);
for (i = 0; i < g_wtp.radios->count; i++) { for (i = 0; i < g_wtp.radios->count; i++) {
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i); struct wtp_radio* radio =
(struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
if (radio->antenna.selections) { if (radio->antenna.selections) {
capwap_array_free(radio->antenna.selections); capwap_array_free(radio->antenna.selections);
} }
if (radio->wlan) { for (i = 0; i < radio->wlan->count; i++) {
for (itemwlan = radio->wlan->first; itemwlan != NULL; itemwlan = itemwlan->next) { struct wtp_radio_wlan *wlan =
struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)itemwlan->item; (struct wtp_radio_wlan *)capwap_array_get_item_pointer(radio->wlan, i);
/* Destroy BSS interface */
if (wlan->wlanhandle)
wifi_wlan_destroy(wlan->wlanhandle);
/* Destroy BSS interface */ capwap_array_free(radio->wlan);
if (wlan->wlanhandle) {
wifi_wlan_destroy(wlan->wlanhandle);
}
}
capwap_list_free(radio->wlan);
}
if (radio->wlanpool) {
for (itemwlan = radio->wlanpool->first; itemwlan != NULL; itemwlan = itemwlan->next) {
struct wtp_radio_wlanpool* wlanpool = (struct wtp_radio_wlanpool*)itemwlan->item;
/* Destroy BSS interface */
if (wlanpool->wlanhandle) {
wifi_wlan_destroy(wlanpool->wlanhandle);
}
}
capwap_list_free(radio->wlanpool);
} }
} }
@ -144,6 +139,36 @@ void wtp_radio_free(void) {
capwap_hash_free(g_wtp.aclstations); capwap_hash_free(g_wtp.aclstations);
} }
/* */
void wtp_radio_reset()
{
int i, j;
if (!g_wtp.radios)
return;
for (i = 0; i < g_wtp.radios->count; i++) {
struct wtp_radio* radio =
(struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
for (j = 0; j < radio->wlan->count; j++) {
struct wtp_radio_wlan *wlan =
(struct wtp_radio_wlan *)capwap_array_get_item_pointer(radio->wlan, j);
/* Destroy WLAN interface */
if (wlan->wlanhandle)
wifi_wlan_stopap(wlan->wlanhandle);
wlan->in_use = 0;
}
radio->initialized = 0;
}
/* Update Event File Descriptor */
wtp_dfa_update_fdspool(&g_wtp.fds);
}
/* */ /* */
int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) { int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
int i; int i;
@ -512,8 +537,7 @@ struct wtp_radio* wtp_radio_create_phy(void) {
radio->status = WTP_RADIO_DISABLED; radio->status = WTP_RADIO_DISABLED;
/* Init configuration radio */ /* Init configuration radio */
radio->wlan = capwap_list_create(); radio->wlan = capwap_array_create(sizeof(struct wtp_radio_wlan), 0, 1);
radio->wlanpool = capwap_list_create();
radio->antenna.selections = capwap_array_create(sizeof(uint8_t), 0, 1); radio->antenna.selections = capwap_array_create(sizeof(uint8_t), 0, 1);
return radio; return radio;
} }
@ -539,10 +563,10 @@ struct wtp_radio* wtp_radio_get_phy(uint8_t radioid) {
} }
/* */ /* */
struct wtp_radio_wlan* wtp_radio_get_wlan(struct wtp_radio* radio, uint8_t wlanid) { struct wtp_radio_wlan *wtp_radio_get_wlan(struct wtp_radio *radio, uint8_t wlanid)
struct capwap_list_item* itemwlan; {
ASSERT(radio != NULL); ASSERT(radio != NULL);
ASSERT(radio->wlan != NULL);
/* Check */ /* Check */
if (!IS_VALID_WLANID(wlanid)) { if (!IS_VALID_WLANID(wlanid)) {
@ -550,37 +574,42 @@ struct wtp_radio_wlan* wtp_radio_get_wlan(struct wtp_radio* radio, uint8_t wlani
return NULL; return NULL;
} }
/* Retrieve BSS */ if (wlanid > radio->wlan->count) {
for (itemwlan = radio->wlan->first; itemwlan != NULL; itemwlan = itemwlan->next) { capwap_logging_warning("wtp_radio_get_wlan: invalid wlanid (%d > %d)",
struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)itemwlan->item; wlanid, radio->wlan->count);
capwap_logging_debug("wtp_radio_get_wlan: checking (%d .. %d)", wlanid, wlan->wlanid); return NULL;
if (wlanid == wlan->wlanid) {
return wlan;
}
} }
return NULL; /* Retrieve BSS */
return (struct wtp_radio_wlan *)capwap_array_get_item_pointer(radio->wlan, wlanid);
} }
/* */ /* */
static struct wtp_radio_wlan* __wtp_radio_search_wlan(struct wtp_radio* radio, const uint8_t* bssid) { static struct wtp_radio_wlan *__wtp_radio_search_wlan(struct wtp_radio *radio, const uint8_t *bssid)
struct capwap_list_item* itemwlan; {
int i;
ASSERT(radio != NULL); ASSERT(radio != NULL);
ASSERT(radio->wlan != NULL);
/* Retrieve BSS */ /* Retrieve BSS */
for (itemwlan = radio->wlan->first; itemwlan != NULL; itemwlan = itemwlan->next) { for (i = 0; i < radio->wlan->count; i++) {
struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)itemwlan->item; struct wtp_radio_wlan *wlan =
if (!memcmp(bssid, wlan->wlanhandle->address, MACADDRESS_EUI48_LENGTH)) { (struct wtp_radio_wlan *)capwap_array_get_item_pointer(radio->wlan, i);
if (!wlan->wlanhandle)
continue;
if (!memcmp(bssid, wlan->wlanhandle->address, MACADDRESS_EUI48_LENGTH))
return wlan; return wlan;
}
} }
return NULL; return NULL;
} }
/* */ /* */
struct wtp_radio_wlan* wtp_radio_search_wlan(struct wtp_radio* radio, const uint8_t* bssid) { struct wtp_radio_wlan *wtp_radio_search_wlan(struct wtp_radio *radio, const uint8_t *bssid)
{
int i; int i;
ASSERT(bssid != NULL); ASSERT(bssid != NULL);
@ -628,12 +657,11 @@ void wtp_radio_receive_data_packet(uint8_t radioid, unsigned short binding, cons
} }
/* */ /* */
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwap_80211_assignbssid_element* bssid) { uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
struct capwap_80211_assignbssid_element* bssid)
{
struct wtp_radio* radio; struct wtp_radio* radio;
struct wtp_radio_wlan* wlan; struct wtp_radio_wlan* wlan;
struct wtp_radio_wlanpool* wlanpool;
struct capwap_list_item* itemwlan;
struct capwap_list_item* itemwlanpool;
struct wlan_startap_params params; struct wlan_startap_params params;
struct capwap_80211_addwlan_element* addwlan; struct capwap_80211_addwlan_element* addwlan;
@ -655,36 +683,22 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
/* Check if virtual interface is already exist */ /* Check if virtual interface is already exist */
wlan = wtp_radio_get_wlan(radio, addwlan->wlanid); wlan = wtp_radio_get_wlan(radio, addwlan->wlanid);
if (wlan) { if (!wlan && !wlan->wlanhandle) {
capwap_logging_debug("Create WLAN: invalid WLAN ID");
return CAPWAP_RESULTCODE_FAILURE;
}
if (wlan->in_use) {
capwap_logging_debug("Create WLAN: vif already exists"); capwap_logging_debug("Create WLAN: vif already exists");
return CAPWAP_RESULTCODE_FAILURE; return CAPWAP_RESULTCODE_FAILURE;
} }
/* Verify exist interface into pool */ /* Prepare physical interface for create wlan */
if (!radio->wlanpool->first) { if (wtp_radio_configure_phy(radio)) {
capwap_logging_debug("Create WLAN: not first if in pool"); capwap_logging_debug("Create WLAN: config phy failed");
return CAPWAP_RESULTCODE_FAILURE; return CAPWAP_RESULTCODE_FAILURE;
} }
/* Prepare physical interface for create wlan */
if (!radio->wlan->count) {
if (wtp_radio_configure_phy(radio)) {
capwap_logging_debug("Create WLAN: config phy failed");
return CAPWAP_RESULTCODE_FAILURE;
}
}
/* Get interface from pool */
itemwlanpool = capwap_itemlist_remove_head(radio->wlanpool);
wlanpool = (struct wtp_radio_wlanpool*)itemwlanpool->item;
/* Create interface used */
itemwlan = capwap_itemlist_create(sizeof(struct wtp_radio_wlan));
wlan = (struct wtp_radio_wlan*)itemwlan->item;
wlan->wlanid = addwlan->wlanid;
wlan->wlanhandle = wlanpool->wlanhandle;
wlan->radio = wlanpool->radio;
/* Wlan configuration */ /* Wlan configuration */
memset(&params, 0, sizeof(struct wlan_startap_params)); memset(&params, 0, sizeof(struct wlan_startap_params));
params.radioid = addwlan->radioid; params.radioid = addwlan->radioid;
@ -699,17 +713,13 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE); params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
/* Start AP */ /* Start AP */
if (wifi_wlan_startap(wlanpool->wlanhandle, &params)) { if (wifi_wlan_startap(wlan->wlanhandle, &params)) {
capwap_logging_debug("Create WLAN: start AP failes"); capwap_logging_debug("Create WLAN: start AP failes");
/* Set interface to pool */
capwap_itemlist_free(itemwlan);
capwap_itemlist_insert_before(radio->wlanpool, NULL, itemwlanpool);
return CAPWAP_RESULTCODE_FAILURE; return CAPWAP_RESULTCODE_FAILURE;
} }
/* Move interface from pool to used */ /* Mark interface as used */
capwap_itemlist_free(itemwlanpool); wlan->in_use = 1;
capwap_itemlist_insert_after(radio->wlan, NULL, itemwlan);
/* Update Event File Descriptor */ /* Update Event File Descriptor */
wtp_dfa_update_fdspool(&g_wtp.fds); wtp_dfa_update_fdspool(&g_wtp.fds);

View File

@ -20,13 +20,7 @@
#define WTP_PREFIX_DEFAULT_NAME "ap" #define WTP_PREFIX_DEFAULT_NAME "ap"
struct wtp_radio_wlan { struct wtp_radio_wlan {
uint8_t wlanid; uint8_t in_use;
struct wifi_wlan* wlanhandle;
struct wtp_radio* radio;
};
/* */
struct wtp_radio_wlanpool {
struct wifi_wlan* wlanhandle; struct wifi_wlan* wlanhandle;
struct wtp_radio* radio; struct wtp_radio* radio;
}; };
@ -38,8 +32,9 @@ struct wtp_radio {
struct wifi_device* devicehandle; struct wifi_device* devicehandle;
char wlanprefix[IFNAMSIZ]; char wlanprefix[IFNAMSIZ];
struct capwap_list* wlan; struct capwap_array* wlan;
struct capwap_list* wlanpool;
int initialized;
int status; int status;
struct capwap_80211_antenna_element antenna; struct capwap_80211_antenna_element antenna;
@ -60,6 +55,7 @@ struct wtp_radio {
void wtp_radio_init(void); void wtp_radio_init(void);
void wtp_radio_close(void); void wtp_radio_close(void);
void wtp_radio_free(void); void wtp_radio_free(void);
void wtp_radio_reset(void);
/* */ /* */
struct wtp_radio* wtp_radio_create_phy(void); struct wtp_radio* wtp_radio_create_phy(void);