From 29623892e185b65a503c925236ff73894a842d38 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 14 Dec 2011 12:20:31 +0100 Subject: [PATCH] mac80211: count authorized stations per BSS Currently, each AP interface will send multicast traffic if any interface has a station entry even if that station entry is allocated only. With the new station state management we can easily fix it by adding a counter that counts each authorized station only and send multicast traffic only when the correct interface has at least one authorized station. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_netdev.c | 2 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/sta_info.c | 14 +++++++++----- net/mac80211/tx.c | 19 ++++++++----------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8df2891..176c08f 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -321,6 +321,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( __IEEE80211_IF_FILE_W(tkip_mic_test); /* AP attributes */ +IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC); IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); @@ -458,6 +459,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(rc_rateidx_mask_2ghz); DEBUGFS_ADD(rc_rateidx_mask_5ghz); + DEBUGFS_ADD(num_sta_authorized); DEBUGFS_ADD(num_sta_ps); DEBUGFS_ADD(dtim_count); DEBUGFS_ADD(num_buffered_multicast); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 96fe754..9516c30 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -243,6 +243,7 @@ struct ieee80211_if_ap { u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; struct sk_buff_head ps_bc_buf; atomic_t num_sta_ps; /* number of stations in PS mode */ + atomic_t num_sta_authorized; /* number of authorized stations */ int dtim_count; bool dtim_bc_mc; }; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index b22775c..141315c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1567,17 +1567,21 @@ int sta_info_move_state_checked(struct sta_info *sta, return -EINVAL; break; case IEEE80211_STA_ASSOC: - if (sta->sta_state == IEEE80211_STA_AUTH) + if (sta->sta_state == IEEE80211_STA_AUTH) { set_bit(WLAN_STA_ASSOC, &sta->_flags); - else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) + } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { + if (sta->sdata->vif.type == NL80211_IFTYPE_AP) + atomic_dec(&sta->sdata->u.ap.num_sta_authorized); clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); - else + } else return -EINVAL; break; case IEEE80211_STA_AUTHORIZED: - if (sta->sta_state == IEEE80211_STA_ASSOC) + if (sta->sta_state == IEEE80211_STA_ASSOC) { + if (sta->sdata->vif.type == NL80211_IFTYPE_AP) + atomic_inc(&sta->sdata->u.ap.num_sta_authorized); set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); - else + } else return -EINVAL; break; default: diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 50c4be9..6bbd6cc 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -304,17 +304,14 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); return TX_DROP; } - } else { - if (unlikely(ieee80211_is_data(hdr->frame_control) && - tx->local->num_sta == 0 && - tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { - /* - * No associated STAs - no need to send multicast - * frames. - */ - return TX_DROP; - } - return TX_CONTINUE; + } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP && + ieee80211_is_data(hdr->frame_control) && + !atomic_read(&tx->sdata->u.ap.num_sta_authorized))) { + /* + * No associated STAs - no need to send multicast + * frames. + */ + return TX_DROP; } return TX_CONTINUE; -- 2.7.4