Commit df323818 authored by Marco Porsch's avatar Marco Porsch Committed by John W. Linville

mac80211: fix unnecessary beacon update after peering status change

ieee80211_bss_info_change_notify is called everytime a peer link is established
or closed, because the accepting_plinks flag in the meshconf IE *might* have changed.

With this patch the corresponding functions return the BSS_CHANGED_BEACON flag when a beacon update is necessary.

Also it makes mesh_accept_plinks_update the common place to update the accepting_plinks flag.
mesh_accept_plinks_update is called upon plink change and also periodically from ieee80211_mesh_housekeeping.
Thus, it also picks up changes of local->num_sta.
Signed-off-by: default avatarMarco Porsch <marco.porsch@etit.tu-chemnitz.de>
Acked-by: default avatarThomas Pedersen <thomas@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent faa97bd4
...@@ -136,10 +136,13 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) ...@@ -136,10 +136,13 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
* mesh_accept_plinks_update - update accepting_plink in local mesh beacons * mesh_accept_plinks_update - update accepting_plink in local mesh beacons
* *
* @sdata: mesh interface in which mesh beacons are going to be updated * @sdata: mesh interface in which mesh beacons are going to be updated
*
* Returns: beacon changed flag if the beacon content changed.
*/ */
void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
{ {
bool free_plinks; bool free_plinks;
u32 changed = 0;
/* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0,
* the mesh interface might be able to establish plinks with peers that * the mesh interface might be able to establish plinks with peers that
...@@ -149,8 +152,12 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) ...@@ -149,8 +152,12 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
*/ */
free_plinks = mesh_plink_availables(sdata); free_plinks = mesh_plink_availables(sdata);
if (free_plinks != sdata->u.mesh.accepting_plinks) if (free_plinks != sdata->u.mesh.accepting_plinks) {
ieee80211_mesh_housekeeping_timer((unsigned long) sdata); sdata->u.mesh.accepting_plinks = free_plinks;
changed = BSS_CHANGED_BEACON;
}
return changed;
} }
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
...@@ -262,7 +269,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) ...@@ -262,7 +269,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
neighbors = (neighbors > 15) ? 15 : neighbors; neighbors = (neighbors > 15) ? 15 : neighbors;
*pos++ = neighbors << 1; *pos++ = neighbors << 1;
/* Mesh capability */ /* Mesh capability */
ifmsh->accepting_plinks = mesh_plink_availables(sdata);
*pos = MESHCONF_CAPAB_FORWARDING; *pos = MESHCONF_CAPAB_FORWARDING;
*pos |= ifmsh->accepting_plinks ? *pos |= ifmsh->accepting_plinks ?
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
...@@ -521,14 +527,13 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, ...@@ -521,14 +527,13 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_mesh *ifmsh) struct ieee80211_if_mesh *ifmsh)
{ {
bool free_plinks; u32 changed;
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
mesh_path_expire(sdata); mesh_path_expire(sdata);
free_plinks = mesh_plink_availables(sdata); changed = mesh_accept_plinks_update(sdata);
if (free_plinks != sdata->u.mesh.accepting_plinks) ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mod_timer(&ifmsh->housekeeping_timer, mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
......
...@@ -282,7 +282,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, ...@@ -282,7 +282,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
u8 *hw_addr, u8 *hw_addr,
struct ieee802_11_elems *ie); struct ieee802_11_elems *ie);
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
void mesh_plink_broken(struct sta_info *sta); void mesh_plink_broken(struct sta_info *sta);
void mesh_plink_deactivate(struct sta_info *sta); void mesh_plink_deactivate(struct sta_info *sta);
int mesh_plink_open(struct sta_info *sta); int mesh_plink_open(struct sta_info *sta);
......
...@@ -48,17 +48,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, ...@@ -48,17 +48,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
u8 *da, __le16 llid, __le16 plid, __le16 reason); u8 *da, __le16 llid, __le16 plid, __le16 reason);
static inline static inline
void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{ {
atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata); return mesh_accept_plinks_update(sdata);
} }
static inline static inline
void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
{ {
atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata); return mesh_accept_plinks_update(sdata);
} }
/** /**
...@@ -170,22 +170,21 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) ...@@ -170,22 +170,21 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
* @sta: mesh peer link to deactivate * @sta: mesh peer link to deactivate
* *
* All mesh paths with this peer as next hop will be flushed * All mesh paths with this peer as next hop will be flushed
* Returns beacon changed flag if the beacon content changed.
* *
* Locking: the caller must hold sta->lock * Locking: the caller must hold sta->lock
*/ */
static bool __mesh_plink_deactivate(struct sta_info *sta) static u32 __mesh_plink_deactivate(struct sta_info *sta)
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
bool deactivated = false; u32 changed = 0;
if (sta->plink_state == NL80211_PLINK_ESTAB) { if (sta->plink_state == NL80211_PLINK_ESTAB)
mesh_plink_dec_estab_count(sdata); changed = mesh_plink_dec_estab_count(sdata);
deactivated = true;
}
sta->plink_state = NL80211_PLINK_BLOCKED; sta->plink_state = NL80211_PLINK_BLOCKED;
mesh_path_flush_by_nexthop(sta); mesh_path_flush_by_nexthop(sta);
return deactivated; return changed;
} }
/** /**
...@@ -198,18 +197,17 @@ static bool __mesh_plink_deactivate(struct sta_info *sta) ...@@ -198,18 +197,17 @@ static bool __mesh_plink_deactivate(struct sta_info *sta)
void mesh_plink_deactivate(struct sta_info *sta) void mesh_plink_deactivate(struct sta_info *sta)
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
bool deactivated; u32 changed;
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
deactivated = __mesh_plink_deactivate(sta); changed = __mesh_plink_deactivate(sta);
sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
sta->sta.addr, sta->llid, sta->plid, sta->sta.addr, sta->llid, sta->plid,
sta->reason); sta->reason);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
if (deactivated) ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
} }
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
...@@ -541,15 +539,14 @@ int mesh_plink_open(struct sta_info *sta) ...@@ -541,15 +539,14 @@ int mesh_plink_open(struct sta_info *sta)
void mesh_plink_block(struct sta_info *sta) void mesh_plink_block(struct sta_info *sta)
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
bool deactivated; u32 changed;
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
deactivated = __mesh_plink_deactivate(sta); changed = __mesh_plink_deactivate(sta);
sta->plink_state = NL80211_PLINK_BLOCKED; sta->plink_state = NL80211_PLINK_BLOCKED;
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
if (deactivated) ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
} }
...@@ -852,9 +849,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -852,9 +849,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
del_timer(&sta->plink_timer); del_timer(&sta->plink_timer);
sta->plink_state = NL80211_PLINK_ESTAB; sta->plink_state = NL80211_PLINK_ESTAB;
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
mesh_plink_inc_estab_count(sdata); changed |= mesh_plink_inc_estab_count(sdata);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
changed |= BSS_CHANGED_BEACON;
mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr); sta->sta.addr);
break; break;
...@@ -888,9 +884,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -888,9 +884,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
del_timer(&sta->plink_timer); del_timer(&sta->plink_timer);
sta->plink_state = NL80211_PLINK_ESTAB; sta->plink_state = NL80211_PLINK_ESTAB;
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
mesh_plink_inc_estab_count(sdata); changed |= mesh_plink_inc_estab_count(sdata);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
changed |= BSS_CHANGED_BEACON;
mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr); sta->sta.addr);
mesh_plink_frame_tx(sdata, mesh_plink_frame_tx(sdata,
...@@ -908,13 +903,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -908,13 +903,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CLS_ACPT: case CLS_ACPT:
reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
sta->reason = reason; sta->reason = reason;
__mesh_plink_deactivate(sta); changed |= __mesh_plink_deactivate(sta);
sta->plink_state = NL80211_PLINK_HOLDING; sta->plink_state = NL80211_PLINK_HOLDING;
llid = sta->llid; llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
changed |= BSS_CHANGED_BEACON;
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
sta->sta.addr, llid, plid, reason); sta->sta.addr, llid, plid, reason);
break; break;
......
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