Commit 00d3f14c authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: use cfg80211s BSS infrastructure

Remove all the code from mac80211 to keep track of BSSes
and use the cfg80211-provided code completely.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 79420f09
...@@ -33,9 +33,9 @@ typedef u16 __nocast zd_addr_t; ...@@ -33,9 +33,9 @@ typedef u16 __nocast zd_addr_t;
#ifdef DEBUG #ifdef DEBUG
# define dev_dbg_f(dev, fmt, args...) \ # define dev_dbg_f(dev, fmt, args...) \
dev_printk_f(KERN_DEBUG, dev, fmt, ## args) dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
# define dev_dbg_f_limit(dev, fmt, args...) do {\ # define dev_dbg_f_limit(dev, fmt, args...) do { \
if (net_ratelimit()) if (net_ratelimit()) \
dev_printk_f(KERN_DEBUG, dev, fmt, ## args) dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
} while (0) } while (0)
#else #else
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
......
...@@ -72,43 +72,36 @@ struct ieee80211_fragment_entry { ...@@ -72,43 +72,36 @@ struct ieee80211_fragment_entry {
struct ieee80211_bss { struct ieee80211_bss {
struct list_head list; /* Yes, this is a hack */
struct ieee80211_bss *hnext; struct cfg80211_bss cbss;
size_t ssid_len;
atomic_t users; /* don't want to look up all the time */
size_t ssid_len;
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 dtim_period; u8 dtim_period;
u16 capability; /* host byte order */
enum ieee80211_band band;
int freq;
int signal, noise, qual;
u8 *ies; /* all information elements from the last Beacon or Probe
* Response frames; note Beacon frame is not allowed to
* override values from Probe Response */
size_t ies_len;
bool wmm_used; bool wmm_used;
unsigned long last_probe_resp;
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
u8 *mesh_id; u8 *mesh_id;
size_t mesh_id_len; size_t mesh_id_len;
u8 *mesh_cfg; u8 *mesh_cfg;
#endif #endif
#define IEEE80211_MAX_SUPP_RATES 32 #define IEEE80211_MAX_SUPP_RATES 32
u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
size_t supp_rates_len; size_t supp_rates_len;
u64 timestamp;
int beacon_int;
unsigned long last_probe_resp; /*
unsigned long last_update; * During assocation, we save an ERP value from a probe response so
/* during assocation, we save an ERP value from a probe response so
* that we can feed ERP info to the driver when handling the * that we can feed ERP info to the driver when handling the
* association completes. these fields probably won't be up-to-date * association completes. these fields probably won't be up-to-date
* otherwise, you probably don't want to use them. */ * otherwise, you probably don't want to use them.
int has_erp_value; */
bool has_erp_value;
u8 erp_value; u8 erp_value;
}; };
...@@ -668,9 +661,6 @@ struct ieee80211_local { ...@@ -668,9 +661,6 @@ struct ieee80211_local {
struct ieee80211_sub_if_data *scan_sdata; struct ieee80211_sub_if_data *scan_sdata;
enum nl80211_channel_type oper_channel_type; enum nl80211_channel_type oper_channel_type;
struct ieee80211_channel *oper_channel, *csa_channel; struct ieee80211_channel *oper_channel, *csa_channel;
struct list_head bss_list;
struct ieee80211_bss *bss_hash[STA_HASH_SIZE];
spinlock_t bss_lock;
/* SNMP counters */ /* SNMP counters */
/* dot11CountersTable */ /* dot11CountersTable */
...@@ -936,8 +926,6 @@ ieee80211_rx_result ...@@ -936,8 +926,6 @@ ieee80211_rx_result
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status); struct ieee80211_rx_status *rx_status);
void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
char *ie, size_t len); char *ie, size_t len);
......
...@@ -734,6 +734,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ...@@ -734,6 +734,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
wiphy->privid = mac80211_wiphy_privid; wiphy->privid = mac80211_wiphy_privid;
wiphy->max_scan_ssids = 4; wiphy->max_scan_ssids = 4;
/* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
sizeof(struct cfg80211_bss);
local = wiphy_priv(wiphy); local = wiphy_priv(wiphy);
local->hw.wiphy = wiphy; local->hw.wiphy = wiphy;
...@@ -877,8 +880,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -877,8 +880,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
mpriv->local = local; mpriv->local = local;
local->mdev = mdev; local->mdev = mdev;
ieee80211_rx_bss_list_init(local);
local->hw.workqueue = local->hw.workqueue =
create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
if (!local->hw.workqueue) { if (!local->hw.workqueue) {
...@@ -1018,7 +1019,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) ...@@ -1018,7 +1019,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
rtnl_unlock(); rtnl_unlock();
ieee80211_rx_bss_list_deinit(local);
ieee80211_clear_tx_pending(local); ieee80211_clear_tx_pending(local);
sta_info_stop(local); sta_info_stop(local);
rate_control_deinitialize(local); rate_control_deinitialize(local);
......
...@@ -275,16 +275,6 @@ u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_t ...@@ -275,16 +275,6 @@ u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_t
& tbl->hash_mask; & tbl->hash_mask;
} }
u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len)
{
if (!mesh_id_len)
return 1;
else if (mesh_id_len == 1)
return (u8) mesh_id[0];
else
return (u8) (mesh_id[0] + 2 * mesh_id[1]);
}
struct mesh_table *mesh_table_alloc(int size_order) struct mesh_table *mesh_table_alloc(int size_order)
{ {
int i; int i;
......
...@@ -196,7 +196,6 @@ struct mesh_rmc { ...@@ -196,7 +196,6 @@ struct mesh_rmc {
/* Public interfaces */ /* Public interfaces */
/* Various */ /* Various */
u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len);
int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
struct ieee80211_sub_if_data *sdata); struct ieee80211_sub_if_data *sdata);
......
This diff is collapsed.
...@@ -12,10 +12,7 @@ ...@@ -12,10 +12,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
/* TODO: /* TODO: figure out how to avoid that the "current BSS" expires */
* figure out how to avoid that the "current BSS" expires
* use cfg80211's BSS handling
*/
#include <linux/wireless.h> #include <linux/wireless.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
...@@ -30,192 +27,29 @@ ...@@ -30,192 +27,29 @@
#define IEEE80211_CHANNEL_TIME (HZ / 33) #define IEEE80211_CHANNEL_TIME (HZ / 33)
#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
{
spin_lock_init(&local->bss_lock);
INIT_LIST_HEAD(&local->bss_list);
}
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
{
struct ieee80211_bss *bss, *tmp;
list_for_each_entry_safe(bss, tmp, &local->bss_list, list)
ieee80211_rx_bss_put(local, bss);
}
struct ieee80211_bss * struct ieee80211_bss *
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len) u8 *ssid, u8 ssid_len)
{ {
struct ieee80211_bss *bss; return (void *)cfg80211_get_bss(local->hw.wiphy,
ieee80211_get_channel(local->hw.wiphy,
spin_lock_bh(&local->bss_lock); freq),
bss = local->bss_hash[STA_HASH(bssid)]; bssid, ssid, ssid_len,
while (bss) { 0, 0);
if (!bss_mesh_cfg(bss) &&
!memcmp(bss->bssid, bssid, ETH_ALEN) &&
bss->freq == freq &&
bss->ssid_len == ssid_len &&
(ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
atomic_inc(&bss->users);
break;
}
bss = bss->hnext;
}
spin_unlock_bh(&local->bss_lock);
return bss;
}
/* Caller must hold local->bss_lock */
static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
struct ieee80211_bss *bss)
{
u8 hash_idx;
if (bss_mesh_cfg(bss))
hash_idx = mesh_id_hash(bss_mesh_id(bss),
bss_mesh_id_len(bss));
else
hash_idx = STA_HASH(bss->bssid);
bss->hnext = local->bss_hash[hash_idx];
local->bss_hash[hash_idx] = bss;
}
/* Caller must hold local->bss_lock */
static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
struct ieee80211_bss *bss)
{
struct ieee80211_bss *b, *prev = NULL;
b = local->bss_hash[STA_HASH(bss->bssid)];
while (b) {
if (b == bss) {
if (!prev)
local->bss_hash[STA_HASH(bss->bssid)] =
bss->hnext;
else
prev->hnext = bss->hnext;
break;
}
prev = b;
b = b->hnext;
}
}
static struct ieee80211_bss *
ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len)
{
struct ieee80211_bss *bss;
bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
if (!bss)
return NULL;
atomic_set(&bss->users, 2);
memcpy(bss->bssid, bssid, ETH_ALEN);
bss->freq = freq;
if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
memcpy(bss->ssid, ssid, ssid_len);
bss->ssid_len = ssid_len;
}
spin_lock_bh(&local->bss_lock);
/* TODO: order by RSSI? */
list_add_tail(&bss->list, &local->bss_list);
__ieee80211_rx_bss_hash_add(local, bss);
spin_unlock_bh(&local->bss_lock);
return bss;
}
#ifdef CONFIG_MAC80211_MESH
static struct ieee80211_bss *
ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
u8 *mesh_cfg, int freq)
{
struct ieee80211_bss *bss;
spin_lock_bh(&local->bss_lock);
bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
while (bss) {
if (bss_mesh_cfg(bss) &&
!memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
bss->freq == freq &&
mesh_id_len == bss->mesh_id_len &&
(mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
mesh_id_len))) {
atomic_inc(&bss->users);
break;
}
bss = bss->hnext;
}
spin_unlock_bh(&local->bss_lock);
return bss;
} }
static struct ieee80211_bss * static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
u8 *mesh_cfg, int mesh_config_len, int freq)
{ {
struct ieee80211_bss *bss; struct ieee80211_bss *bss = (void *)cbss;
if (mesh_config_len != IEEE80211_MESH_CONFIG_LEN)
return NULL;
bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
if (!bss)
return NULL;
bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
if (!bss->mesh_cfg) {
kfree(bss);
return NULL;
}
if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
if (!bss->mesh_id) {
kfree(bss->mesh_cfg);
kfree(bss);
return NULL;
}
memcpy(bss->mesh_id, mesh_id, mesh_id_len);
}
atomic_set(&bss->users, 2);
memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
bss->mesh_id_len = mesh_id_len;
bss->freq = freq;
spin_lock_bh(&local->bss_lock);
/* TODO: order by RSSI? */
list_add_tail(&bss->list, &local->bss_list);
__ieee80211_rx_bss_hash_add(local, bss);
spin_unlock_bh(&local->bss_lock);
return bss;
}
#endif
static void ieee80211_rx_bss_free(struct ieee80211_bss *bss)
{
kfree(bss->ies);
kfree(bss_mesh_id(bss)); kfree(bss_mesh_id(bss));
kfree(bss_mesh_cfg(bss)); kfree(bss_mesh_cfg(bss));
kfree(bss);
} }
void ieee80211_rx_bss_put(struct ieee80211_local *local, void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_bss *bss) struct ieee80211_bss *bss)
{ {
local_bh_disable(); cfg80211_put_bss((struct cfg80211_bss *)bss);
if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) {
local_bh_enable();
return;
}
__ieee80211_rx_bss_hash_del(local, bss);
list_del(&bss->list);
spin_unlock_bh(&local->bss_lock);
ieee80211_rx_bss_free(bss);
} }
struct ieee80211_bss * struct ieee80211_bss *
...@@ -228,7 +62,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -228,7 +62,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bool beacon) bool beacon)
{ {
struct ieee80211_bss *bss; struct ieee80211_bss *bss;
int clen, freq = channel->center_freq; int clen;
enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE; enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE;
s32 signal = 0; s32 signal = 0;
...@@ -240,39 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -240,39 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
signal = (rx_status->signal * 100) / local->hw.max_signal; signal = (rx_status->signal * 100) / local->hw.max_signal;
} }
cfg80211_put_bss( bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
cfg80211_inform_bss_frame(local->hw.wiphy, channel, mgmt, len, signal, sigtype,
mgmt, len, signal, sigtype, GFP_ATOMIC);
GFP_ATOMIC));
#ifdef CONFIG_MAC80211_MESH if (!bss)
if (elems->mesh_config) return NULL;
bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id,
elems->mesh_id_len, elems->mesh_config, freq); bss->cbss.free_priv = ieee80211_rx_bss_free;
else
#endif
bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq,
elems->ssid, elems->ssid_len);
if (!bss) {
#ifdef CONFIG_MAC80211_MESH
if (elems->mesh_config)
bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id,
elems->mesh_id_len, elems->mesh_config,
elems->mesh_config_len, freq);
else
#endif
bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq,
elems->ssid, elems->ssid_len);
if (!bss)
return NULL;
} else {
#if 0
/* TODO: order by RSSI? */
spin_lock_bh(&local->bss_lock);
list_move_tail(&bss->list, &local->bss_list);
spin_unlock_bh(&local->bss_lock);
#endif
}
/* save the ERP value so that it is available at association time */ /* save the ERP value so that it is available at association time */
if (elems->erp_info && elems->erp_info_len >= 1) { if (elems->erp_info && elems->erp_info_len >= 1) {
...@@ -280,9 +89,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -280,9 +89,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->has_erp_value = 1; bss->has_erp_value = 1;
} }
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
if (elems->tim) { if (elems->tim) {
struct ieee80211_tim_ie *tim_ie = struct ieee80211_tim_ie *tim_ie =
(struct ieee80211_tim_ie *)elems->tim; (struct ieee80211_tim_ie *)elems->tim;
...@@ -311,34 +117,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -311,34 +117,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->supp_rates_len += clen; bss->supp_rates_len += clen;
} }
bss->band = rx_status->band;
bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
bss->last_update = jiffies;
bss->signal = rx_status->signal;
bss->noise = rx_status->noise;
bss->qual = rx_status->qual;
bss->wmm_used = elems->wmm_param || elems->wmm_info; bss->wmm_used = elems->wmm_param || elems->wmm_info;
if (!beacon) if (!beacon)
bss->last_probe_resp = jiffies; bss->last_probe_resp = jiffies;
/*
* For probe responses, or if we don't have any information yet,
* use the IEs from the beacon.
*/
if (!bss->ies || !beacon) {
if (bss->ies == NULL || bss->ies_len < elems->total_len) {
kfree(bss->ies);
bss->ies = kmalloc(elems->total_len, GFP_ATOMIC);
}
if (bss->ies) {
memcpy(bss->ies, elems->ie_start, elems->total_len);
bss->ies_len = elems->total_len;
} else
bss->ies_len = 0;
}
return bss; return bss;
} }
...@@ -350,7 +133,7 @@ void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid, ...@@ -350,7 +133,7 @@ void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len); bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
if (bss) { if (bss) {
atomic_dec(&bss->users); cfg80211_unlink_bss(local->hw.wiphy, (void *)bss);
ieee80211_rx_bss_put(local, bss); ieee80211_rx_bss_put(local, bss);
} }
} }
......
...@@ -102,8 +102,9 @@ void ieee80211_chswitch_work(struct work_struct *work) ...@@ -102,8 +102,9 @@ void ieee80211_chswitch_work(struct work_struct *work)
goto exit; goto exit;
sdata->local->oper_channel = sdata->local->csa_channel; sdata->local->oper_channel = sdata->local->csa_channel;
/* XXX: shouldn't really modify cfg80211-owned data! */
if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL)) if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
bss->freq = sdata->local->oper_channel->center_freq; bss->cbss.channel = sdata->local->oper_channel;
ieee80211_rx_bss_put(sdata->local, bss); ieee80211_rx_bss_put(sdata->local, bss);
exit: exit:
...@@ -158,7 +159,9 @@ void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -158,7 +159,9 @@ void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
IEEE80211_QUEUE_STOP_REASON_CSA); IEEE80211_QUEUE_STOP_REASON_CSA);
ifsta->flags |= IEEE80211_STA_CSA_RECEIVED; ifsta->flags |= IEEE80211_STA_CSA_RECEIVED;
mod_timer(&ifsta->chswitch_timer, mod_timer(&ifsta->chswitch_timer,
jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int)); jiffies +
msecs_to_jiffies(sw_elem->count *
bss->cbss.beacon_interval));
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment