mac80211: add unified BSS configuration

This patch (based on Ron Rindjunsky's) creates a framework for
a unified way to pass BSS configuration to drivers that require
the information, e.g. for implementing power save mode.

This patch introduces new ieee80211_bss_conf structure that is
passed to the driver via the new bss_info_changed() callback
when the BSS configuration changes.

This new BSS configuration infrastructure adds the following
new features:
 * drivers are notified of their association AID
 * drivers are notified of association status

and replaces the erp_ie_changed() callback. The patch also does
the relevant driver updates for the latter change.

Signed-off-by: Ron Rindjunsky <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
This commit is contained in:
Johannes Berg 2007-12-28 14:32:58 +01:00 • committed by David S. Miller
commit 471b3efdfc
19 changed files with 183 additions and 120 deletions

View file

@ -118,7 +118,7 @@ static ssize_t ieee80211_if_fmt_flags(
sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
sdata->flags & IEEE80211_SDATA_USE_PROTECTION ? "CTS prot\n" : "");
sdata->bss_conf.use_cts_prot ? "CTS prot\n" : "");
}
__IEEE80211_IF_FILE(flags);

View file

@ -635,25 +635,30 @@ int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
return 0;
}
void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes)
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (local->ops->erp_ie_changed)
local->ops->erp_ie_changed(local_to_hw(local), changes,
!!(sdata->flags & IEEE80211_SDATA_USE_PROTECTION),
!(sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE));
struct ieee80211_local *local = sdata->local;
if (!changed)
return;
if (local->ops->bss_info_changed)
local->ops->bss_info_changed(local_to_hw(local),
&sdata->vif,
&sdata->bss_conf,
changed);
}
void ieee80211_reset_erp_info(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
sdata->flags &= ~(IEEE80211_SDATA_USE_PROTECTION |
IEEE80211_SDATA_SHORT_PREAMBLE);
ieee80211_erp_info_change_notify(dev,
IEEE80211_ERP_CHANGE_PROTECTION |
IEEE80211_ERP_CHANGE_PREAMBLE);
sdata->bss_conf.use_cts_prot = 0;
sdata->bss_conf.use_short_preamble = 0;
ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_ERP_CTS_PROT |
BSS_CHANGED_ERP_PREAMBLE);
}
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,

View file

@ -291,12 +291,7 @@ struct ieee80211_if_sta {
/* flags used in struct ieee80211_sub_if_data.flags */
#define IEEE80211_SDATA_ALLMULTI BIT(0)
#define IEEE80211_SDATA_PROMISC BIT(1)
#define IEEE80211_SDATA_USE_PROTECTION BIT(2) /* CTS protect ERP frames */
/* use short preamble with IEEE 802.11b: this flag is set when the AP or beacon
* generator reports that there are no present stations that cannot support short
* preambles */
#define IEEE80211_SDATA_SHORT_PREAMBLE BIT(3)
#define IEEE80211_SDATA_USERSPACE_MLME BIT(4)
#define IEEE80211_SDATA_USERSPACE_MLME BIT(2)
struct ieee80211_sub_if_data {
struct list_head list;
@ -327,6 +322,15 @@ struct ieee80211_sub_if_data {
struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
struct ieee80211_key *default_key;
/*
* BSS configuration for this interface.
*
* FIXME: I feel bad putting this here when we already have a
* bss pointer, but the bss pointer is just wrong when
* you have multiple virtual STA mode interfaces...
* This needs to be fixed.
*/
struct ieee80211_bss_conf bss_conf;
struct ieee80211_if_ap *bss; /* BSS that this device belongs to */
union {
@ -770,7 +774,8 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
u8 *addr);
int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed);
void ieee80211_reset_erp_info(struct net_device *dev);
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
struct ieee80211_ht_info *ht_info);

View file

@ -313,48 +313,42 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
}
static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
u8 erp_value)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
int preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0;
u8 changes = 0;
bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
bool preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0;
DECLARE_MAC_BUF(mac);
u32 changed = 0;
if (use_protection != !!(sdata->flags & IEEE80211_SDATA_USE_PROTECTION)) {
if (use_protection != bss_conf->use_cts_prot) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
"%s)\n",
dev->name,
sdata->dev->name,
use_protection ? "enabled" : "disabled",
print_mac(mac, ifsta->bssid));
}
if (use_protection)
sdata->flags |= IEEE80211_SDATA_USE_PROTECTION;
else
sdata->flags &= ~IEEE80211_SDATA_USE_PROTECTION;
changes |= IEEE80211_ERP_CHANGE_PROTECTION;
bss_conf->use_cts_prot = use_protection;
changed |= BSS_CHANGED_ERP_CTS_PROT;
}
if (preamble_mode != !(sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE)) {
if (preamble_mode != bss_conf->use_short_preamble) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: switched to %s barker preamble"
" (BSSID=%s)\n",
dev->name,
sdata->dev->name,
(preamble_mode == WLAN_ERP_PREAMBLE_SHORT) ?
"short" : "long",
print_mac(mac, ifsta->bssid));
}
if (preamble_mode)
sdata->flags &= ~IEEE80211_SDATA_SHORT_PREAMBLE;
else
sdata->flags |= IEEE80211_SDATA_SHORT_PREAMBLE;
changes |= IEEE80211_ERP_CHANGE_PREAMBLE;
bss_conf->use_short_preamble = preamble_mode;
changed |= BSS_CHANGED_ERP_PREAMBLE;
}
if (changes)
ieee80211_erp_info_change_notify(dev, changes);
return changed;
}
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
@ -458,19 +452,16 @@ static void ieee80211_set_associated(struct net_device *dev,
struct ieee80211_if_sta *ifsta,
bool assoc)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
union iwreq_data wrqu;
if (!!(ifsta->flags & IEEE80211_STA_ASSOCIATED) == assoc)
return;
u32 changed = BSS_CHANGED_ASSOC;
if (assoc) {
struct ieee80211_sub_if_data *sdata;
struct ieee80211_sta_bss *bss;
ifsta->flags |= IEEE80211_STA_ASSOCIATED;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
return;
@ -479,7 +470,8 @@ static void ieee80211_set_associated(struct net_device *dev,
ifsta->ssid, ifsta->ssid_len);
if (bss) {
if (bss->has_erp_value)
ieee80211_handle_erp_ie(dev, bss->erp_value);
changed |= ieee80211_handle_erp_ie(
sdata, bss->erp_value);
ieee80211_rx_bss_put(dev, bss);
}
@ -499,6 +491,8 @@ static void ieee80211_set_associated(struct net_device *dev,
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
ifsta->last_probe = jiffies;
ieee80211_led_assoc(local, assoc);
ieee80211_bss_info_change_notify(sdata, changed);
}
static void ieee80211_set_disassoc(struct net_device *dev,
@ -1536,18 +1530,20 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
}
static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_sta *ifsta,
struct ieee80211_mgmt *mgmt,
size_t len,
int reassoc)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_local *local = sdata->local;
struct net_device *dev = sdata->dev;
struct ieee80211_hw_mode *mode;
struct sta_info *sta;
u32 rates;
u16 capab_info, status_code, aid;
struct ieee802_11_elems elems;
struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
u8 *pos;
int i, j;
DECLARE_MAC_BUF(mac);
@ -1620,6 +1616,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
if (ifsta->assocresp_ies)
memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
/* set AID, ieee80211_set_associated() will tell the driver */
bss_conf->aid = aid;
ieee80211_set_associated(dev, ifsta, 1);
/* Add STA entry for the AP */
@ -2099,6 +2097,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
struct ieee802_11_elems elems;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_conf *conf = &local->hw.conf;
u32 changed = 0;
ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
@ -2119,7 +2118,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
if (elems.erp_info && elems.erp_info_len >= 1)
ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
if (elems.ht_cap_elem && elems.ht_info_elem &&
elems.wmm_param && local->ops->conf_ht &&
@ -2142,6 +2141,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
elems.wmm_param_len);
}
ieee80211_bss_info_change_notify(sdata, changed);
}
@ -2329,10 +2330,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
break;
case IEEE80211_STYPE_ASSOC_RESP:
ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 0);
ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
break;
case IEEE80211_STYPE_REASSOC_RESP:
ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 1);
ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
break;
case IEEE80211_STYPE_DEAUTH:
ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
@ -2787,7 +2788,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
break;
}
control.tx_rate =
((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) &&
(sdata->bss_conf.use_short_preamble &&
(ratesel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
ratesel.rate->val2 : ratesel.rate->val;
control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;

View file

@ -176,7 +176,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
* to closest integer */
dur = ieee80211_frame_duration(local, 10, rate, erp,
tx->sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE);
tx->sdata->bss_conf.use_short_preamble);
if (next_frag_len) {
/* Frame is fragmented: duration increases with time needed to
@ -185,8 +185,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
/* next fragment */
dur += ieee80211_frame_duration(local, next_frag_len,
txrate->rate, erp,
tx->sdata->flags &
IEEE80211_SDATA_SHORT_PREAMBLE);
tx->sdata->bss_conf.use_short_preamble);
}
return dur;
@ -605,7 +604,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
tx->u.tx.control->alt_retry_rate = -1;
if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
(tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) &&
tx->sdata->bss_conf.use_cts_prot &&
(tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) {
tx->u.tx.last_frag_rate = tx->u.tx.rate;
if (rsel.probe)
@ -667,7 +666,7 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
if (mode->mode == MODE_IEEE80211G &&
(tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
(tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
(tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) &&
tx->sdata->bss_conf.use_cts_prot &&
!(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
@ -676,7 +675,7 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
* available on the network at the current point in time. */
if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
(tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
(tx->sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) &&
tx->sdata->bss_conf.use_short_preamble &&
(!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
}
@ -1754,7 +1753,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
}
control->tx_rate =
((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) &&
(sdata->bss_conf.use_short_preamble &&
(rsel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
rsel.rate->val2 : rsel.rate->val;
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;

View file

@ -312,8 +312,8 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
int erp;
erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
dur = ieee80211_frame_duration(local, frame_len, rate,
erp, sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE);
dur = ieee80211_frame_duration(local, frame_len, rate, erp,
sdata->bss_conf.use_short_preamble);
return cpu_to_le16(dur);
}
@ -326,11 +326,11 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_rate *rate;
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
int short_preamble;
bool short_preamble;
int erp;
u16 dur;
short_preamble = sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE;
short_preamble = sdata->bss_conf.use_short_preamble;
rate = frame_txctl->rts_rate;
erp = !!(rate->flags & IEEE80211_RATE_ERP);
@ -357,11 +357,11 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_rate *rate;
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
int short_preamble;
bool short_preamble;
int erp;
u16 dur;
short_preamble = sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE;
short_preamble = sdata->bss_conf.use_short_preamble;
rate = frame_txctl->rts_rate;
erp = !!(rate->flags & IEEE80211_RATE_ERP);