* [PATCH] mac80211: Add capability to enable/disable beaconing @ 2009-01-20 7:57 Sujith 2009-01-20 10:52 ` Johannes Berg 0 siblings, 1 reply; 8+ messages in thread From: Sujith @ 2009-01-20 7:57 UTC (permalink / raw) To: linville; +Cc: linux-wireless, johannes, Jouni.Malinen This patch adds a flag to notify drivers to start and stop beaconing when needed, for example, during a scan run. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> --- include/net/mac80211.h | 3 +++ net/mac80211/main.c | 10 ++++++++++ net/mac80211/scan.c | 3 +++ 3 files changed, 16 insertions(+), 0 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9a5869e..a9f71b5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -637,6 +637,8 @@ enum ieee80211_if_conf_change { * * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. * @bssid: BSSID of the network we are associated to/creating. + * @enable_beacon: Indicates whether beacons can be sent. + * This is valid only for AP/IBSS/MESH modes. * * This structure is passed to the config_interface() callback of * &struct ieee80211_hw. @@ -644,6 +646,7 @@ enum ieee80211_if_conf_change { struct ieee80211_if_conf { u32 changed; u8 *bssid; + bool enable_beacon; }; /** diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c78304d..44585c7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -183,6 +183,16 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) return -EINVAL; } + if ((changed & IEEE80211_IFCC_BEACON) && + (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) { + if (local->sw_scanning || local->hw_scanning) + conf.enable_beacon = false; + else + conf.enable_beacon = true; + } + if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) return -EINVAL; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a2caeed..c8be92d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -459,6 +459,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) local->sw_scanning = false; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); netif_tx_lock_bh(local->mdev); netif_addr_lock(local->mdev); @@ -655,6 +656,8 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, local->scan_band = IEEE80211_BAND_2GHZ; local->scan_sdata = scan_sdata; + ieee80211_if_config(scan_sdata, IEEE80211_IFCC_BEACON); + netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; local->ops->configure_filter(local_to_hw(local), -- 1.6.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] mac80211: Add capability to enable/disable beaconing 2009-01-20 7:57 [PATCH] mac80211: Add capability to enable/disable beaconing Sujith @ 2009-01-20 10:52 ` Johannes Berg 2009-01-20 16:00 ` Sujith 0 siblings, 1 reply; 8+ messages in thread From: Johannes Berg @ 2009-01-20 10:52 UTC (permalink / raw) To: Sujith; +Cc: linville, linux-wireless, Jouni.Malinen [-- Attachment #1: Type: text/plain, Size: 953 bytes --] cOn Tue, 2009-01-20 at 13:27 +0530, Sujith wrote: > This patch adds a flag to notify drivers to start and > stop beaconing when needed, for example, during a scan run. > + if ((changed & IEEE80211_IFCC_BEACON) && > + (sdata->vif.type == NL80211_IFTYPE_AP || > + sdata->vif.type == NL80211_IFTYPE_ADHOC || > + sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) { > + if (local->sw_scanning || local->hw_scanning) > + conf.enable_beacon = false; > + else > + conf.enable_beacon = true; > + } > + You really just want to do the minimal thing, right? :) That won't work when userspace disables the beacon by removing it, for instance, right now drivers won't know when hostapd removed the beacon except that ieee80211_beacon_get will start returning 0... Also, I think a separate change flag would be appropriate, sometimes we might just re-enable the beacon without having changed it, after scanning? johannes [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] mac80211: Add capability to enable/disable beaconing 2009-01-20 10:52 ` Johannes Berg @ 2009-01-20 16:00 ` Sujith 2009-01-20 19:54 ` Luis R. Rodriguez 2009-01-21 11:45 ` Johannes Berg 0 siblings, 2 replies; 8+ messages in thread From: Sujith @ 2009-01-20 16:00 UTC (permalink / raw) To: Johannes Berg; +Cc: linville, linux-wireless, Jouni.Malinen Johannes Berg wrote: > cOn Tue, 2009-01-20 at 13:27 +0530, Sujith wrote: > > This patch adds a flag to notify drivers to start and > > stop beaconing when needed, for example, during a scan run. > > > > + if ((changed & IEEE80211_IFCC_BEACON) && > > + (sdata->vif.type == NL80211_IFTYPE_AP || > > + sdata->vif.type == NL80211_IFTYPE_ADHOC || > > + sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) { > > + if (local->sw_scanning || local->hw_scanning) > > + conf.enable_beacon = false; > > + else > > + conf.enable_beacon = true; > > + } > > + > > You really just want to do the minimal thing, right? :) Oh, absolutely :) > That won't work when userspace disables the beacon by removing it, for > instance, right now drivers won't know when hostapd removed the beacon > except that ieee80211_beacon_get will start returning 0... Also, I think > a separate change flag would be appropriate, sometimes we might just > re-enable the beacon without having changed it, after scanning? Ok, how about this ? diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9a5869e..72a3025 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -624,12 +624,18 @@ struct ieee80211_if_init_conf { * enum ieee80211_if_conf_change - interface config change flags * * @IEEE80211_IFCC_BSSID: The BSSID changed. - * @IEEE80211_IFCC_BEACON: The beacon for this interface changed - * (currently AP and MESH only), use ieee80211_beacon_get(). + * @IEEE80211_IFCC_CONFIGURE_BEACON: The beacon for this interface changed + * (currently AP,IBSS and MESH only), use ieee80211_beacon_get(). + * @IEEE80211_IFCC_STOP_BEACON: Indicates that beaconing should be stopped + * by the driver. + * @IEEE80211_IFCC_RESUME_BEACON: Beaconing can be resumed by the driver, + * with the original template obtained from mac80211. */ enum ieee80211_if_conf_change { - IEEE80211_IFCC_BSSID = BIT(0), - IEEE80211_IFCC_BEACON = BIT(1), + IEEE80211_IFCC_BSSID = BIT(0), + IEEE80211_IFCC_CONFIGURE_BEACON = BIT(1), + IEEE80211_IFCC_STOP_BEACON = BIT(2), + IEEE80211_IFCC_RESUME_BEACON = BIT(3) }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d1ac3ab..b6d718c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -523,7 +523,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + return ieee80211_if_config(sdata, IEEE80211_IFCC_CONFIGURE_BEACON); } static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -583,7 +583,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) synchronize_rcu(); kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + return ieee80211_if_config(sdata, IEEE80211_IFCC_STOP_BEACON); } /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 82f568e..988827c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -427,7 +427,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.mesh.accepting_plinks) - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_CONFIGURE_BEACON); ifmsh->housekeeping = false; mod_timer(&ifmsh->housekeeping_timer, @@ -442,7 +442,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ifmsh->housekeeping = true; queue_work(local->hw.workqueue, &ifmsh->work); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_CONFIGURE_BEACON); } void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 81c5cff..59197bd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1598,7 +1598,7 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ifsta->probe_resp = skb; - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_CONFIGURE_BEACON); rates = 0; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a2caeed..09f4839 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -459,6 +459,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) local->sw_scanning = false; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + ieee80211_if_config(sdata, IEEE80211_IFCC_RESUME_BEACON); netif_tx_lock_bh(local->mdev); netif_addr_lock(local->mdev); @@ -655,6 +656,8 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, local->scan_band = IEEE80211_BAND_2GHZ; local->scan_sdata = scan_sdata; + ieee80211_if_config(scan_sdata, IEEE80211_IFCC_STOP_BEACON); + netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; local->ops->configure_filter(local_to_hw(local), ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] mac80211: Add capability to enable/disable beaconing 2009-01-20 16:00 ` Sujith @ 2009-01-20 19:54 ` Luis R. Rodriguez 2009-01-21 11:45 ` Johannes Berg 1 sibling, 0 replies; 8+ messages in thread From: Luis R. Rodriguez @ 2009-01-20 19:54 UTC (permalink / raw) To: Sujith Cc: Johannes Berg, linville@tuxdriver.com, linux-wireless@vger.kernel.org, Jouni Malinen On Tue, Jan 20, 2009 at 08:00:08AM -0800, Sujith wrote: > Johannes Berg wrote: > > cOn Tue, 2009-01-20 at 13:27 +0530, Sujith wrote: > > > This patch adds a flag to notify drivers to start and > > > stop beaconing when needed, for example, during a scan run. > > > > > > > + if ((changed & IEEE80211_IFCC_BEACON) && > > > + (sdata->vif.type == NL80211_IFTYPE_AP || > > > + sdata->vif.type == NL80211_IFTYPE_ADHOC || > > > + sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) { > > > + if (local->sw_scanning || local->hw_scanning) > > > + conf.enable_beacon = false; > > > + else > > > + conf.enable_beacon = true; > > > + } > > > + > > > > You really just want to do the minimal thing, right? :) > > Oh, absolutely :) > > > That won't work when userspace disables the beacon by removing it, for > > instance, right now drivers won't know when hostapd removed the beacon > > except that ieee80211_beacon_get will start returning 0... Also, I think > > a separate change flag would be appropriate, sometimes we might just > > re-enable the beacon without having changed it, after scanning? > > Ok, how about this ? > > diff --git a/include/net/mac80211.h b/include/net/mac80211.h > index 9a5869e..72a3025 100644 > --- a/include/net/mac80211.h > +++ b/include/net/mac80211.h > @@ -624,12 +624,18 @@ struct ieee80211_if_init_conf { > * enum ieee80211_if_conf_change - interface config change flags > * > * @IEEE80211_IFCC_BSSID: The BSSID changed. > - * @IEEE80211_IFCC_BEACON: The beacon for this interface changed > - * (currently AP and MESH only), use ieee80211_beacon_get(). > + * @IEEE80211_IFCC_CONFIGURE_BEACON: The beacon for this interface changed > + * (currently AP,IBSS and MESH only), use ieee80211_beacon_get(). > + * @IEEE80211_IFCC_STOP_BEACON: Indicates that beaconing should be stopped > + * by the driver. > + * @IEEE80211_IFCC_RESUME_BEACON: Beaconing can be resumed by the driver, > + * with the original template obtained from mac80211. > */ > enum ieee80211_if_conf_change { > - IEEE80211_IFCC_BSSID = BIT(0), > - IEEE80211_IFCC_BEACON = BIT(1), > + IEEE80211_IFCC_BSSID = BIT(0), > + IEEE80211_IFCC_CONFIGURE_BEACON = BIT(1), > + IEEE80211_IFCC_STOP_BEACON = BIT(2), > + IEEE80211_IFCC_RESUME_BEACON = BIT(3) This would make grep'ing easier: IEEE80211_IFCC_BEACON_CONFIGURE = BIT(1), IEEE80211_IFCC_BEACON_STOP = BIT(2), IEEE80211_IFCC_BEACON_RESUME = BIT(3) Luis ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] mac80211: Add capability to enable/disable beaconing 2009-01-20 16:00 ` Sujith 2009-01-20 19:54 ` Luis R. Rodriguez @ 2009-01-21 11:45 ` Johannes Berg 2009-01-21 13:02 ` Johannes Berg 1 sibling, 1 reply; 8+ messages in thread From: Johannes Berg @ 2009-01-21 11:45 UTC (permalink / raw) To: Sujith; +Cc: linville, linux-wireless, Jouni.Malinen [-- Attachment #1.1: Type: text/plain, Size: 1216 bytes --] On Tue, 2009-01-20 at 21:30 +0530, Sujith wrote: > Johannes Berg wrote: > > cOn Tue, 2009-01-20 at 13:27 +0530, Sujith wrote: > > > This patch adds a flag to notify drivers to start and > > > stop beaconing when needed, for example, during a scan run. > > > > > > > + if ((changed & IEEE80211_IFCC_BEACON) && > > > + (sdata->vif.type == NL80211_IFTYPE_AP || > > > + sdata->vif.type == NL80211_IFTYPE_ADHOC || > > > + sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) { > > > + if (local->sw_scanning || local->hw_scanning) > > > + conf.enable_beacon = false; > > > + else > > > + conf.enable_beacon = true; > > > + } > > > + > > > > You really just want to do the minimal thing, right? :) > > Oh, absolutely :) :) > > That won't work when userspace disables the beacon by removing it, for > > instance, right now drivers won't know when hostapd removed the beacon > > except that ieee80211_beacon_get will start returning 0... Also, I think > > a separate change flag would be appropriate, sometimes we might just > > re-enable the beacon without having changed it, after scanning? > > Ok, how about this ? How about this? Untested still though. johannes [-- Attachment #1.2: 015-mac80211-add-iflock.patch --] [-- Type: message/rfc822, Size: 4451 bytes --] From: Subject: mac80211: add interface list lock Date: Wed, 21 Jan 2009 12:45:47 +0100 Message-ID: <1232538347.4358.3.camel@johannes.local> Using only the RTNL has a number of problems, most notably that ieee80211_iterate_active_interfaces() and other interface list traversals cannot be done from the internal workqueue because it needs to be flushed under the RTNL. This patch introduces a new mutex that protects the interface list against modifications. A more detailed explanation is part of the code change. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- Need this for the scan stuff I'm doing next, but this has the side effect of allowing you to call ieee80211_iterate_active_interfaces() from mac80211's workqueue, which might be interesting. net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/iface.c | 24 ++++++++++++++++++++++++ net/mac80211/main.c | 3 +++ net/mac80211/util.c | 4 ++-- 4 files changed, 31 insertions(+), 2 deletions(-) --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-01-21 12:19:47.000000000 +0100 +++ wireless-testing/net/mac80211/ieee80211_i.h 2009-01-21 12:22:02.000000000 +0100 @@ -643,7 +643,9 @@ struct ieee80211_local { struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; + /* see iface.c */ struct list_head interfaces; + struct mutex iflist_mtx; /* * Key lock, protects sdata's key_list and sta_info's --- wireless-testing.orig/net/mac80211/iface.c 2009-01-21 12:20:40.000000000 +0100 +++ wireless-testing/net/mac80211/iface.c 2009-01-21 12:28:15.000000000 +0100 @@ -21,6 +21,23 @@ #include "mesh.h" #include "led.h" +/** + * DOC: Interface list locking + * + * The interface list in each struct ieee80211_local is protected + * three-fold: + * + * (1) modifications may only be done under the RTNL + * (2) modifications and readers are protected against each other by + * the iflist_mtx. + * (3) modifications are done in an RCU manner so atomic readers + * can traverse the list in RCU-safe blocks. + * + * As a consequence, reads (traversals) of the list can be protected + * by either the RTNL, the iflist_mtx or RCU. + */ + + static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { int meshhdrlen; @@ -800,7 +817,9 @@ int ieee80211_if_add(struct ieee80211_lo params->mesh_id_len, params->mesh_id); + mutex_lock(&local->iflist_mtx); list_add_tail_rcu(&sdata->list, &local->interfaces); + mutex_unlock(&local->iflist_mtx); if (new_dev) *new_dev = ndev; @@ -816,7 +835,10 @@ void ieee80211_if_remove(struct ieee8021 { ASSERT_RTNL(); + mutex_lock(&sdata->local->iflist_mtx); list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); + synchronize_rcu(); unregister_netdevice(sdata->dev); } @@ -831,8 +853,10 @@ void ieee80211_remove_interfaces(struct ASSERT_RTNL(); + mutex_lock(&local->iflist_mtx); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_del(&sdata->list); unregister_netdevice(sdata->dev); } + mutex_unlock(&local->iflist_mtx); } --- wireless-testing.orig/net/mac80211/main.c 2009-01-21 12:26:36.000000000 +0100 +++ wireless-testing/net/mac80211/main.c 2009-01-21 12:27:19.000000000 +0100 @@ -718,6 +718,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( local->hw.conf.radio_enabled = true; INIT_LIST_HEAD(&local->interfaces); + mutex_init(&local->iflist_mtx); spin_lock_init(&local->key_lock); @@ -968,6 +969,8 @@ void ieee80211_free_hw(struct ieee80211_ { struct ieee80211_local *local = hw_to_local(hw); + mutex_destroy(&local->iflist_mtx); + wiphy_free(local->hw.wiphy); } EXPORT_SYMBOL(ieee80211_free_hw); --- wireless-testing.orig/net/mac80211/util.c 2009-01-21 12:28:36.000000000 +0100 +++ wireless-testing/net/mac80211/util.c 2009-01-21 12:29:01.000000000 +0100 @@ -459,7 +459,7 @@ void ieee80211_iterate_active_interfaces struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - rtnl_lock(); + mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { switch (sdata->vif.type) { @@ -480,7 +480,7 @@ void ieee80211_iterate_active_interfaces &sdata->vif); } - rtnl_unlock(); + mutex_unlock(&local->iflist_mtx); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); [-- Attachment #1.3: 016-mac80211-beacon-endis.patch --] [-- Type: message/rfc822, Size: 7442 bytes --] From: Subject: mac80211: Add capability to enable/disable beaconing Date: Wed, 21 Jan 2009 12:45:47 +0100 Message-ID: <1232538347.4358.4.camel@johannes.local> This patch adds a flag to notify drivers to start and stop beaconing when needed, for example, during a scan run. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- include/net/mac80211.h | 9 +++++++-- net/mac80211/cfg.c | 5 +++-- net/mac80211/main.c | 42 +++++++++++++++++++++++++++++++++++++++++- net/mac80211/mesh.c | 3 ++- net/mac80211/mlme.c | 3 ++- net/mac80211/scan.c | 18 +++++++++++------- 6 files changed, 66 insertions(+), 14 deletions(-) --- wireless-testing.orig/include/net/mac80211.h 2009-01-21 12:44:02.000000000 +0100 +++ wireless-testing/include/net/mac80211.h 2009-01-21 12:44:16.000000000 +0100 @@ -626,10 +626,12 @@ struct ieee80211_if_init_conf { * @IEEE80211_IFCC_BSSID: The BSSID changed. * @IEEE80211_IFCC_BEACON: The beacon for this interface changed * (currently AP and MESH only), use ieee80211_beacon_get(). + * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed. */ enum ieee80211_if_conf_change { - IEEE80211_IFCC_BSSID = BIT(0), - IEEE80211_IFCC_BEACON = BIT(1), + IEEE80211_IFCC_BSSID = BIT(0), + IEEE80211_IFCC_BEACON = BIT(1), + IEEE80211_IFCC_BEACON_ENABLED = BIT(2), }; /** @@ -637,6 +639,8 @@ enum ieee80211_if_conf_change { * * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. * @bssid: BSSID of the network we are associated to/creating. + * @enable_beacon: Indicates whether beacons can be sent. + * This is valid only for AP/IBSS/MESH modes. * * This structure is passed to the config_interface() callback of * &struct ieee80211_hw. @@ -644,6 +648,7 @@ enum ieee80211_if_conf_change { struct ieee80211_if_conf { u32 changed; const u8 *bssid; + bool enable_beacon; }; /** --- wireless-testing.orig/net/mac80211/main.c 2009-01-21 12:44:04.000000000 +0100 +++ wireless-testing/net/mac80211/main.c 2009-01-21 12:44:16.000000000 +0100 @@ -168,7 +168,6 @@ int ieee80211_if_config(struct ieee80211 return 0; memset(&conf, 0, sizeof(conf)); - conf.changed = changed; if (sdata->vif.type == NL80211_IFTYPE_STATION || sdata->vif.type == NL80211_IFTYPE_ADHOC) @@ -183,9 +182,50 @@ int ieee80211_if_config(struct ieee80211 return -EINVAL; } + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + break; + default: + /* do not warn to simplify caller in scan.c */ + changed &= ~IEEE80211_IFCC_BEACON_ENABLED; + if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) + return -EINVAL; + changed &= ~IEEE80211_IFCC_BEACON; + break; + } + + if (changed & IEEE80211_IFCC_BEACON_ENABLED) { + if (local->sw_scanning) { + conf.enable_beacon = false; + } else { + /* + * Beacon should be enabled, but AP mode must + * check whether there is a beacon configured. + */ + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + conf.enable_beacon = + !!rcu_dereference(sdata->u.ap.beacon); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + conf.enable_beacon = true; + break; + default: + /* not reached */ + WARN_ON(1); + break; + } + } + } + if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) return -EINVAL; + conf.changed = changed; + return local->ops->config_interface(local_to_hw(local), &sdata->vif, &conf); } --- wireless-testing.orig/net/mac80211/scan.c 2009-01-21 12:43:32.000000000 +0100 +++ wireless-testing/net/mac80211/scan.c 2009-01-21 12:44:16.000000000 +0100 @@ -20,6 +20,7 @@ #include <linux/wireless.h> #include <linux/if_arp.h> +#include <linux/rtnetlink.h> #include <net/mac80211.h> #include <net/iw_handler.h> @@ -472,8 +473,8 @@ void ieee80211_scan_completed(struct iee netif_addr_unlock(local->mdev); netif_tx_unlock_bh(local->mdev); - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { /* Tell AP we're back */ if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { @@ -482,8 +483,10 @@ void ieee80211_scan_completed(struct iee } } else netif_tx_wake_all_queues(sdata->dev); + + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); } - rcu_read_unlock(); + mutex_unlock(&local->iflist_mtx); done: ieee80211_mlme_notify_scan_completed(local); @@ -491,7 +494,6 @@ void ieee80211_scan_completed(struct iee } EXPORT_SYMBOL(ieee80211_scan_completed); - void ieee80211_scan_work(struct work_struct *work) { struct ieee80211_local *local = @@ -633,8 +635,10 @@ int ieee80211_start_scan(struct ieee8021 local->sw_scanning = true; - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); + if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { netif_tx_stop_all_queues(sdata->dev); @@ -643,7 +647,7 @@ int ieee80211_start_scan(struct ieee8021 } else netif_tx_stop_all_queues(sdata->dev); } - rcu_read_unlock(); + mutex_unlock(&local->iflist_mtx); if (ssid) { local->scan_ssid_len = ssid_len; --- wireless-testing.orig/net/mac80211/mesh.c 2009-01-21 12:43:32.000000000 +0100 +++ wireless-testing/net/mac80211/mesh.c 2009-01-21 12:44:16.000000000 +0100 @@ -442,7 +442,8 @@ void ieee80211_start_mesh(struct ieee802 ifmsh->housekeeping = true; queue_work(local->hw.workqueue, &ifmsh->work); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED); } void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) --- wireless-testing.orig/net/mac80211/mlme.c 2009-01-21 12:43:32.000000000 +0100 +++ wireless-testing/net/mac80211/mlme.c 2009-01-21 12:44:16.000000000 +0100 @@ -1598,7 +1598,8 @@ static int ieee80211_sta_join_ibss(struc ifsta->probe_resp = skb; - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED); rates = 0; --- wireless-testing.orig/net/mac80211/cfg.c 2009-01-21 12:43:32.000000000 +0100 +++ wireless-testing/net/mac80211/cfg.c 2009-01-21 12:44:16.000000000 +0100 @@ -523,7 +523,8 @@ static int ieee80211_config_beacon(struc kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED); } static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -583,7 +584,7 @@ static int ieee80211_del_beacon(struct w synchronize_rcu(); kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); } /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] mac80211: Add capability to enable/disable beaconing 2009-01-21 11:45 ` Johannes Berg @ 2009-01-21 13:02 ` Johannes Berg 2009-01-22 3:28 ` Sujith 0 siblings, 1 reply; 8+ messages in thread From: Johannes Berg @ 2009-01-21 13:02 UTC (permalink / raw) To: Sujith; +Cc: linville, linux-wireless, Jouni.Malinen [-- Attachment #1.1: Type: text/plain, Size: 205 bytes --] On Wed, 2009-01-21 at 12:45 +0100, Johannes Berg wrote: > How about this? Untested still though. That ran into a bug, here's a version that's hopefully better. (second patch unchanged) johannes [-- Attachment #1.2: 015-mac80211-add-iflock.patch --] [-- Type: message/rfc822, Size: 4679 bytes --] From: Subject: mac80211: add interface list lock Date: Wed, 21 Jan 2009 14:02:35 +0100 Message-ID: <1232542955.6059.0.camel@johannes.local> Using only the RTNL has a number of problems, most notably that ieee80211_iterate_active_interfaces() and other interface list traversals cannot be done from the internal workqueue because it needs to be flushed under the RTNL. This patch introduces a new mutex that protects the interface list against modifications. A more detailed explanation is part of the code change. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- Need this for the scan stuff I'm doing next, but this has the side effect of allowing you to call ieee80211_iterate_active_interfaces() from mac80211's workqueue, which might be interesting. net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/iface.c | 31 +++++++++++++++++++++++++++++++ net/mac80211/main.c | 3 +++ net/mac80211/util.c | 4 ++-- 4 files changed, 38 insertions(+), 2 deletions(-) --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-01-21 12:48:12.000000000 +0100 +++ wireless-testing/net/mac80211/ieee80211_i.h 2009-01-21 13:57:49.000000000 +0100 @@ -643,7 +643,9 @@ struct ieee80211_local { struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; + /* see iface.c */ struct list_head interfaces; + struct mutex iflist_mtx; /* * Key lock, protects sdata's key_list and sta_info's --- wireless-testing.orig/net/mac80211/iface.c 2009-01-21 12:48:12.000000000 +0100 +++ wireless-testing/net/mac80211/iface.c 2009-01-21 13:57:49.000000000 +0100 @@ -21,6 +21,23 @@ #include "mesh.h" #include "led.h" +/** + * DOC: Interface list locking + * + * The interface list in each struct ieee80211_local is protected + * three-fold: + * + * (1) modifications may only be done under the RTNL + * (2) modifications and readers are protected against each other by + * the iflist_mtx. + * (3) modifications are done in an RCU manner so atomic readers + * can traverse the list in RCU-safe blocks. + * + * As a consequence, reads (traversals) of the list can be protected + * by either the RTNL, the iflist_mtx or RCU. + */ + + static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { int meshhdrlen; @@ -800,7 +817,9 @@ int ieee80211_if_add(struct ieee80211_lo params->mesh_id_len, params->mesh_id); + mutex_lock(&local->iflist_mtx); list_add_tail_rcu(&sdata->list, &local->interfaces); + mutex_unlock(&local->iflist_mtx); if (new_dev) *new_dev = ndev; @@ -816,7 +835,10 @@ void ieee80211_if_remove(struct ieee8021 { ASSERT_RTNL(); + mutex_lock(&sdata->local->iflist_mtx); list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); + synchronize_rcu(); unregister_netdevice(sdata->dev); } @@ -832,7 +854,16 @@ void ieee80211_remove_interfaces(struct ASSERT_RTNL(); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { + /* + * we cannot hold the iflist_mtx across unregister_netdevice, + * but we only need to hold it for list modifications to lock + * out readers since we're under the RTNL here as all other + * writers. + */ + mutex_lock(&local->iflist_mtx); list_del(&sdata->list); + mutex_unlock(&local->iflist_mtx); + unregister_netdevice(sdata->dev); } } --- wireless-testing.orig/net/mac80211/main.c 2009-01-21 12:48:21.000000000 +0100 +++ wireless-testing/net/mac80211/main.c 2009-01-21 13:57:50.000000000 +0100 @@ -718,6 +718,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( local->hw.conf.radio_enabled = true; INIT_LIST_HEAD(&local->interfaces); + mutex_init(&local->iflist_mtx); spin_lock_init(&local->key_lock); @@ -968,6 +969,8 @@ void ieee80211_free_hw(struct ieee80211_ { struct ieee80211_local *local = hw_to_local(hw); + mutex_destroy(&local->iflist_mtx); + wiphy_free(local->hw.wiphy); } EXPORT_SYMBOL(ieee80211_free_hw); --- wireless-testing.orig/net/mac80211/util.c 2009-01-21 12:48:12.000000000 +0100 +++ wireless-testing/net/mac80211/util.c 2009-01-21 12:48:21.000000000 +0100 @@ -459,7 +459,7 @@ void ieee80211_iterate_active_interfaces struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - rtnl_lock(); + mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { switch (sdata->vif.type) { @@ -480,7 +480,7 @@ void ieee80211_iterate_active_interfaces &sdata->vif); } - rtnl_unlock(); + mutex_unlock(&local->iflist_mtx); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] mac80211: Add capability to enable/disable beaconing 2009-01-21 13:02 ` Johannes Berg @ 2009-01-22 3:28 ` Sujith 0 siblings, 0 replies; 8+ messages in thread From: Sujith @ 2009-01-22 3:28 UTC (permalink / raw) To: Johannes Berg Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org, Jouni Malinen Johannes Berg wrote: > On Wed, 2009-01-21 at 12:45 +0100, Johannes Berg wrote: > > > How about this? Untested still though. > > That ran into a bug, here's a version that's hopefully better. (second > patch unchanged) Tested in IBSS mode, works fine. Thanks a lot. Sujith ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] mac80211: Add capability to enable/disable beaconing
@ 2009-01-22 17:07 Johannes Berg
0 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2009-01-22 17:07 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Sujith Manoharan
This patch adds a flag to notify drivers to start and stop
beaconing when needed, for example, during a scan run. Based
on Sujith's first patch to do the same, but now disables
beaconing for all virtual interfaces while scanning, has a
separate change flag and tracks user-space requests.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/mac80211.h | 9 +++++++--
net/mac80211/cfg.c | 5 +++--
net/mac80211/main.c | 42 +++++++++++++++++++++++++++++++++++++++++-
net/mac80211/mesh.c | 3 ++-
net/mac80211/mlme.c | 3 ++-
net/mac80211/scan.c | 18 +++++++++++-------
6 files changed, 66 insertions(+), 14 deletions(-)
--- wireless-testing.orig/include/net/mac80211.h 2009-01-21 12:48:21.000000000 +0100
+++ wireless-testing/include/net/mac80211.h 2009-01-21 12:48:21.000000000 +0100
@@ -626,10 +626,12 @@ struct ieee80211_if_init_conf {
* @IEEE80211_IFCC_BSSID: The BSSID changed.
* @IEEE80211_IFCC_BEACON: The beacon for this interface changed
* (currently AP and MESH only), use ieee80211_beacon_get().
+ * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed.
*/
enum ieee80211_if_conf_change {
- IEEE80211_IFCC_BSSID = BIT(0),
- IEEE80211_IFCC_BEACON = BIT(1),
+ IEEE80211_IFCC_BSSID = BIT(0),
+ IEEE80211_IFCC_BEACON = BIT(1),
+ IEEE80211_IFCC_BEACON_ENABLED = BIT(2),
};
/**
@@ -637,6 +639,8 @@ enum ieee80211_if_conf_change {
*
* @changed: parameters that have changed, see &enum ieee80211_if_conf_change.
* @bssid: BSSID of the network we are associated to/creating.
+ * @enable_beacon: Indicates whether beacons can be sent.
+ * This is valid only for AP/IBSS/MESH modes.
*
* This structure is passed to the config_interface() callback of
* &struct ieee80211_hw.
@@ -644,6 +648,7 @@ enum ieee80211_if_conf_change {
struct ieee80211_if_conf {
u32 changed;
const u8 *bssid;
+ bool enable_beacon;
};
/**
--- wireless-testing.orig/net/mac80211/main.c 2009-01-21 12:48:21.000000000 +0100
+++ wireless-testing/net/mac80211/main.c 2009-01-21 12:48:21.000000000 +0100
@@ -168,7 +168,6 @@ int ieee80211_if_config(struct ieee80211
return 0;
memset(&conf, 0, sizeof(conf));
- conf.changed = changed;
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC)
@@ -183,9 +182,50 @@ int ieee80211_if_config(struct ieee80211
return -EINVAL;
}
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
+ default:
+ /* do not warn to simplify caller in scan.c */
+ changed &= ~IEEE80211_IFCC_BEACON_ENABLED;
+ if (WARN_ON(changed & IEEE80211_IFCC_BEACON))
+ return -EINVAL;
+ changed &= ~IEEE80211_IFCC_BEACON;
+ break;
+ }
+
+ if (changed & IEEE80211_IFCC_BEACON_ENABLED) {
+ if (local->sw_scanning) {
+ conf.enable_beacon = false;
+ } else {
+ /*
+ * Beacon should be enabled, but AP mode must
+ * check whether there is a beacon configured.
+ */
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP:
+ conf.enable_beacon =
+ !!rcu_dereference(sdata->u.ap.beacon);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ conf.enable_beacon = true;
+ break;
+ default:
+ /* not reached */
+ WARN_ON(1);
+ break;
+ }
+ }
+ }
+
if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
return -EINVAL;
+ conf.changed = changed;
+
return local->ops->config_interface(local_to_hw(local),
&sdata->vif, &conf);
}
--- wireless-testing.orig/net/mac80211/scan.c 2009-01-21 12:48:12.000000000 +0100
+++ wireless-testing/net/mac80211/scan.c 2009-01-21 12:48:21.000000000 +0100
@@ -20,6 +20,7 @@
#include <linux/wireless.h>
#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
#include <net/mac80211.h>
#include <net/iw_handler.h>
@@ -472,8 +473,8 @@ void ieee80211_scan_completed(struct iee
netif_addr_unlock(local->mdev);
netif_tx_unlock_bh(local->mdev);
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
/* Tell AP we're back */
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
@@ -482,8 +483,10 @@ void ieee80211_scan_completed(struct iee
}
} else
netif_tx_wake_all_queues(sdata->dev);
+
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
}
- rcu_read_unlock();
+ mutex_unlock(&local->iflist_mtx);
done:
ieee80211_mlme_notify_scan_completed(local);
@@ -491,7 +494,6 @@ void ieee80211_scan_completed(struct iee
}
EXPORT_SYMBOL(ieee80211_scan_completed);
-
void ieee80211_scan_work(struct work_struct *work)
{
struct ieee80211_local *local =
@@ -633,8 +635,10 @@ int ieee80211_start_scan(struct ieee8021
local->sw_scanning = true;
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
+
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
netif_tx_stop_all_queues(sdata->dev);
@@ -643,7 +647,7 @@ int ieee80211_start_scan(struct ieee8021
} else
netif_tx_stop_all_queues(sdata->dev);
}
- rcu_read_unlock();
+ mutex_unlock(&local->iflist_mtx);
if (ssid) {
local->scan_ssid_len = ssid_len;
--- wireless-testing.orig/net/mac80211/mesh.c 2009-01-21 12:48:12.000000000 +0100
+++ wireless-testing/net/mac80211/mesh.c 2009-01-21 12:48:21.000000000 +0100
@@ -442,7 +442,8 @@ void ieee80211_start_mesh(struct ieee802
ifmsh->housekeeping = true;
queue_work(local->hw.workqueue, &ifmsh->work);
- ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
+ IEEE80211_IFCC_BEACON_ENABLED);
}
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
--- wireless-testing.orig/net/mac80211/mlme.c 2009-01-21 12:48:12.000000000 +0100
+++ wireless-testing/net/mac80211/mlme.c 2009-01-21 12:48:21.000000000 +0100
@@ -1598,7 +1598,8 @@ static int ieee80211_sta_join_ibss(struc
ifsta->probe_resp = skb;
- ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
+ IEEE80211_IFCC_BEACON_ENABLED);
rates = 0;
--- wireless-testing.orig/net/mac80211/cfg.c 2009-01-21 12:48:12.000000000 +0100
+++ wireless-testing/net/mac80211/cfg.c 2009-01-21 12:48:21.000000000 +0100
@@ -523,7 +523,8 @@ static int ieee80211_config_beacon(struc
kfree(old);
- return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+ return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
+ IEEE80211_IFCC_BEACON_ENABLED);
}
static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
@@ -583,7 +584,7 @@ static int ieee80211_del_beacon(struct w
synchronize_rcu();
kfree(old);
- return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+ return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
}
/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
^ permalink raw reply [flat|nested] 8+ messages in threadend of thread, other threads:[~2009-01-23 16:35 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-01-20 7:57 [PATCH] mac80211: Add capability to enable/disable beaconing Sujith 2009-01-20 10:52 ` Johannes Berg 2009-01-20 16:00 ` Sujith 2009-01-20 19:54 ` Luis R. Rodriguez 2009-01-21 11:45 ` Johannes Berg 2009-01-21 13:02 ` Johannes Berg 2009-01-22 3:28 ` Sujith -- strict thread matches above, loose matches on Subject: below -- 2009-01-22 17:07 Johannes Berg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).