Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 278979
b: refs/heads/master
c: d9a7ddb
h: refs/heads/master
i:
  278977: adc4db5
  278975: 7018796
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Dec 15, 2011
1 parent 097f484 commit e950492
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 87be1e1e00f870567780dec111193426b4c085e8
refs/heads/master: d9a7ddb05e5419ca5e4b54f57074dc33c7ea991c
76 changes: 61 additions & 15 deletions trunk/net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,10 +746,11 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
netif_rx_ni(skb);
}

static void sta_apply_parameters(struct ieee80211_local *local,
struct sta_info *sta,
struct station_parameters *params)
static int sta_apply_parameters(struct ieee80211_local *local,
struct sta_info *sta,
struct station_parameters *params)
{
int ret = 0;
u32 rates;
int i, j;
struct ieee80211_supported_band *sband;
Expand All @@ -761,13 +762,59 @@ static void sta_apply_parameters(struct ieee80211_local *local,
mask = params->sta_flags_mask;
set = params->sta_flags_set;

/*
* In mesh mode, we can clear AUTHENTICATED flag but must
* also make ASSOCIATED follow appropriately for the driver
* API. See also below, after AUTHORIZED changes.
*/
if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
/* cfg80211 should not allow this in non-mesh modes */
if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
return -EINVAL;

if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
!test_sta_flag(sta, WLAN_STA_AUTH)) {
ret = sta_info_move_state_checked(sta,
IEEE80211_STA_AUTH);
if (ret)
return ret;
ret = sta_info_move_state_checked(sta,
IEEE80211_STA_ASSOC);
if (ret)
return ret;
}
}

if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
set_sta_flag(sta, WLAN_STA_AUTHORIZED);
ret = sta_info_move_state_checked(sta,
IEEE80211_STA_AUTHORIZED);
else
clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
ret = sta_info_move_state_checked(sta,
IEEE80211_STA_ASSOC);
if (ret)
return ret;
}

if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
/* cfg80211 should not allow this in non-mesh modes */
if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
return -EINVAL;

if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
test_sta_flag(sta, WLAN_STA_AUTH)) {
ret = sta_info_move_state_checked(sta,
IEEE80211_STA_AUTH);
if (ret)
return ret;
ret = sta_info_move_state_checked(sta,
IEEE80211_STA_NONE);
if (ret)
return ret;
}
}


if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
Expand All @@ -792,13 +839,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
clear_sta_flag(sta, WLAN_STA_MFP);
}

if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
set_sta_flag(sta, WLAN_STA_AUTH);
else
clear_sta_flag(sta, WLAN_STA_AUTH);
}

if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
set_sta_flag(sta, WLAN_STA_TDLS_PEER);
Expand Down Expand Up @@ -870,6 +910,8 @@ static void sta_apply_parameters(struct ieee80211_local *local,
}
#endif
}

return 0;
}

static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
Expand Down Expand Up @@ -900,10 +942,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
if (!sta)
return -ENOMEM;

set_sta_flag(sta, WLAN_STA_AUTH);
set_sta_flag(sta, WLAN_STA_ASSOC);
sta_info_move_state(sta, IEEE80211_STA_AUTH);
sta_info_move_state(sta, IEEE80211_STA_ASSOC);

sta_apply_parameters(local, sta, params);
err = sta_apply_parameters(local, sta, params);
if (err) {
sta_info_free(local, sta);
return err;
}

/*
* for TDLS, rate control should be initialized only when supported
Expand Down
5 changes: 4 additions & 1 deletion trunk/net/mac80211/ibss.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,10 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
return NULL;

sta->last_rx = jiffies;
set_sta_flag(sta, WLAN_STA_AUTHORIZED);

sta_info_move_state(sta, IEEE80211_STA_AUTH);
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);

/* make sure mandatory rates are always added */
sta->sta.supp_rates[band] = supp_rates |
Expand Down
5 changes: 3 additions & 2 deletions trunk/net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
goto err_del_interface;
}

/* no atomic bitop required since STA is not live yet */
set_sta_flag(sta, WLAN_STA_AUTHORIZED);
sta_info_move_state(sta, IEEE80211_STA_AUTH);
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);

res = sta_info_insert(sta);
if (res) {
Expand Down
7 changes: 5 additions & 2 deletions trunk/net/mac80211/mesh_plink.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,12 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
if (!sta)
return NULL;

set_sta_flag(sta, WLAN_STA_AUTH);
set_sta_flag(sta, WLAN_STA_AUTHORIZED);
sta_info_move_state(sta, IEEE80211_STA_AUTH);
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);

set_sta_flag(sta, WLAN_STA_WME);

sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
if (elems->ht_cap_elem)
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
Expand Down
6 changes: 3 additions & 3 deletions trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -1577,10 +1577,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
return false;
}

set_sta_flag(sta, WLAN_STA_AUTH);
set_sta_flag(sta, WLAN_STA_ASSOC);
sta_info_move_state(sta, IEEE80211_STA_AUTH);
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
set_sta_flag(sta, WLAN_STA_AUTHORIZED);
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);

rates = 0;
basic_rates = 0;
Expand Down
65 changes: 59 additions & 6 deletions trunk/net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
}

/**
* __sta_info_free - internal STA free helper
* sta_info_free - free STA
*
* @local: pointer to the global information
* @sta: STA info to free
*
* This function must undo everything done by sta_info_alloc()
* that may happen before sta_info_insert().
* that may happen before sta_info_insert(). It may only be
* called when sta_info_insert() has not been attempted (and
* if that fails, the station is freed anyway.)
*/
static void __sta_info_free(struct ieee80211_local *local,
struct sta_info *sta)
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
{
if (sta->rate_ctrl) {
rate_control_free_sta(sta);
Expand Down Expand Up @@ -598,7 +599,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
return 0;
out_free:
BUG_ON(!err);
__sta_info_free(local, sta);
sta_info_free(local, sta);
return err;
}

Expand Down Expand Up @@ -905,6 +906,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);

while (sta->sta_state > IEEE80211_STA_NONE)
sta_info_move_state(sta, sta->sta_state - 1);

if (sta->uploaded) {
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
Expand Down Expand Up @@ -974,7 +978,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
kfree_rcu(tid_tx, rcu_head);
}

__sta_info_free(local, sta);
sta_info_free(local, sta);

return 0;
}
Expand Down Expand Up @@ -1538,3 +1542,52 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
sta_info_recalc_tim(sta);
}
EXPORT_SYMBOL(ieee80211_sta_set_buffered);

int sta_info_move_state_checked(struct sta_info *sta,
enum ieee80211_sta_state new_state)
{
/* might_sleep(); -- for driver notify later, fix IBSS first */

if (sta->sta_state == new_state)
return 0;

switch (new_state) {
case IEEE80211_STA_NONE:
if (sta->sta_state == IEEE80211_STA_AUTH)
clear_bit(WLAN_STA_AUTH, &sta->_flags);
else
return -EINVAL;
break;
case IEEE80211_STA_AUTH:
if (sta->sta_state == IEEE80211_STA_NONE)
set_bit(WLAN_STA_AUTH, &sta->_flags);
else if (sta->sta_state == IEEE80211_STA_ASSOC)
clear_bit(WLAN_STA_ASSOC, &sta->_flags);
else
return -EINVAL;
break;
case IEEE80211_STA_ASSOC:
if (sta->sta_state == IEEE80211_STA_AUTH)
set_bit(WLAN_STA_ASSOC, &sta->_flags);
else if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
else
return -EINVAL;
break;
case IEEE80211_STA_AUTHORIZED:
if (sta->sta_state == IEEE80211_STA_ASSOC)
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
else
return -EINVAL;
break;
default:
WARN(1, "invalid state %d", new_state);
return -EINVAL;
}

printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
sta->sdata->name, sta->sta.addr, new_state);
sta->sta_state = new_state;

return 0;
}
37 changes: 37 additions & 0 deletions trunk/net/mac80211/sta_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ enum ieee80211_sta_info_flags {
WLAN_STA_4ADDR_EVENT,
};

enum ieee80211_sta_state {
/* NOTE: These need to be ordered correctly! */
IEEE80211_STA_NONE,
IEEE80211_STA_AUTH,
IEEE80211_STA_ASSOC,
IEEE80211_STA_AUTHORIZED,
};

#define STA_TID_NUM 16
#define ADDBA_RESP_INTERVAL HZ
#define HT_AGG_MAX_RETRIES 0x3
Expand Down Expand Up @@ -262,6 +270,7 @@ struct sta_ampdu_mlme {
* @dummy: indicate a dummy station created for receiving
* EAP frames before association
* @sta: station information we share with the driver
* @sta_state: duplicates information about station state (for debug)
*/
struct sta_info {
/* General information, mostly static */
Expand All @@ -283,6 +292,8 @@ struct sta_info {

bool uploaded;

enum ieee80211_sta_state sta_state;

/* use the accessors defined below */
unsigned long _flags;

Expand Down Expand Up @@ -371,12 +382,18 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta)
static inline void set_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{
WARN_ON(flag == WLAN_STA_AUTH ||
flag == WLAN_STA_ASSOC ||
flag == WLAN_STA_AUTHORIZED);
set_bit(flag, &sta->_flags);
}

static inline void clear_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{
WARN_ON(flag == WLAN_STA_AUTH ||
flag == WLAN_STA_ASSOC ||
flag == WLAN_STA_AUTHORIZED);
clear_bit(flag, &sta->_flags);
}

Expand All @@ -389,15 +406,32 @@ static inline int test_sta_flag(struct sta_info *sta,
static inline int test_and_clear_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{
WARN_ON(flag == WLAN_STA_AUTH ||
flag == WLAN_STA_ASSOC ||
flag == WLAN_STA_AUTHORIZED);
return test_and_clear_bit(flag, &sta->_flags);
}

static inline int test_and_set_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{
WARN_ON(flag == WLAN_STA_AUTH ||
flag == WLAN_STA_ASSOC ||
flag == WLAN_STA_AUTHORIZED);
return test_and_set_bit(flag, &sta->_flags);
}

int sta_info_move_state_checked(struct sta_info *sta,
enum ieee80211_sta_state new_state);

static inline void sta_info_move_state(struct sta_info *sta,
enum ieee80211_sta_state new_state)
{
int ret = sta_info_move_state_checked(sta, new_state);
WARN_ON_ONCE(ret);
}


void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
struct tid_ampdu_tx *tid_tx);

Expand Down Expand Up @@ -489,6 +523,9 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
*/
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
u8 *addr, gfp_t gfp);

void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);

/*
* Insert STA info into hash table/list, returns zero or a
* -EEXIST if (if the same MAC address is already present).
Expand Down
1 change: 0 additions & 1 deletion trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)

if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
if (unlikely(!assoc &&
tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
ieee80211_is_data(hdr->frame_control))) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: dropped data frame to not "
Expand Down

0 comments on commit e950492

Please sign in to comment.