Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: Bayesian rate control
From: Adrian Chadd @ 2016-11-05  5:09 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Björn Smedman, linux-wireless@vger.kernel.org, ath9k-devel
In-Reply-To: <1477461362.4059.17.camel@sipsolutions.net>

Hi,

On 25 October 2016 at 22:56, Johannes Berg <johannes@sipsolutions.net> wrote:
>
>> The intel 7260 and later parts also allow user controllable rate
>> control and provide transmit completion feedback, but I don't know
>> whether it's enough for your needs.
>
> Perhaps. However, existing rate control is *very* tightly coupled to
> the driver, and it'd be fairly pointless to disentangle just for the
> sake of playing with a rate control algorithm.
>
> Also, the device doesn't support per-frame control nor any kind of
> sampling-with-table-fallback, only the rate table that you give to the
> device and update.

Hi,

But there is a per-descriptor TX rate table entry in the driver.
FreeBSD uses it to implement its rate control for the intel drivers.

What am I missing? :)

>
> Btw, mac80211_hwsim with wmediumd doing some medium simulation might
> also be something to look at for just extending to VHT.
>
> And come to think of it, there's this new driver Felix et al have been
> working on, mt7601u, which also should support proper rate control
> APIs.



-adrian

^ permalink raw reply

* Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: Sebastian Gottschall @ 2016-11-05  8:05 UTC (permalink / raw)
  To: Ben Greear, yu-chieh kung, Bruno Antunes
  Cc: Mauro Mozzarelli, linux-wireless@vger.kernel.org,
	OpenWrt Development List, ath10k@lists.infradead.org
In-Reply-To: <68bd7ebd-b12a-5dbf-a267-5913127718a1@candelatech.com>

would be good if qca can fix this bug finally in all available 
firmwares. its a very annoying issue since a long time

Sebastian


Am 04.11.2016 um 23:23 schrieb Ben Greear:
> The bug appears that vlan-tx-stripping is unconditionally enabled in
> at least my firmware.  I have re-compiled w/out that flag set, and it 
> appears
> to work for me.
>
> Please download this firmware, rename it firmware-2.bin, make sure you 
> remove/rename
> any firmware-5.bin (etc) so mine will load, and see if that fixes your 
> problem.
>
> Please note that it is very likely you will have to use same MAC address
> for the VLAN devices that the underlying station uses in order for 
> this to work.
>
> https://www.candelatech.com/downloads/tmp/firmware-2-full-community.bin
>
>
> Thanks,
> Ben
>
>
> On 11/04/2016 02:50 PM, Ben Greear wrote:
>> I can reproduce this in my CT firmware. I'll see if I can fix it,
>> but for stock firmware, it might be that changing the driver to use 
>> Ethernet packet type
>> of native-wifi would make .1q vlans work.
>>
>> Thanks,
>> Ben
>>
>> On 11/04/2016 10:28 AM, yu-chieh kung wrote:
>>> I met the same problem before,
>>> if i modify the 1q header to other value (0xaa00) before go into 
>>> firmware.
>>> I can capture the packet in the air
>>> I think the vlan packet is dropped in firmware.
>>>
>>> 2016-11-04 22:41 GMT+08:00 Bruno Antunes <baantunes@gmail.com>:
>>>> On 4 November 2016 at 14:18, Mauro Mozzarelli 
>>>> <openwrt@ezplanet.net> wrote:
>>>>> Since the capability is implemented in software you might be 
>>>>> testing the
>>>>> limit of your router's CPU i/o speed.
>>>>
>>>> By loading the module in rawmode?
>>>>
>>>> The AP is an APU and Sta is an APU2.
>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 04/11/16 14:13, Bruno Antunes wrote:
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> Old thread but I think the issue is still present.
>>>>>>
>>>>>> I'm running a setup with VLANs with WDS and ath10k cards.
>>>>>>
>>>>>> To make it work both cards must be loaded in rawmode, AP
>>>>>> and Sta, and with no security.
>>>>>>
>>>>>> I'm using a OpenWrt trunk r49941 and the most recent firmware,
>>>>>> 10.2.4.70.58, from Kalle ath10k firmware tree.
>>>>>>
>>>>>> Although it works the throughput is very bad.
>>>>>> Are there any alternatives to improve the throughput.
>>>>>>
>>>>>> Best Regards,
>>>>>> Bruno
>>>>>>
>>>>>> On 9 December 2015 at 17:24, voncken <cedric.voncken@acksys.fr> 
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>> -----Message d'origine-----
>>>>>>>> De : Ben Greear [mailto:greearb@candelatech.com]
>>>>>>>> Envoyé : mercredi 9 décembre 2015 16:34
>>>>>>>> À : Cedric VONCKEN; ath10k@lists.infradead.org; linux-wireless
>>>>>>>> Objet : Re: ATH10K VLAN firmware issue
>>>>>>>>
>>>>>>>> This only happens when you use STA  + WDS, or is .1q broken for 
>>>>>>>> you in
>>>>>>>> other cases as well?
>>>>>>>
>>>>>>> No, this issue occurs in all modes (STA, STA + WDS, AP).
>>>>>>>
>>>>>>> Thanks
>>>>>>>
>>>>>>> Cedric.
>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Ben
>>>>>>>>
>>>>>>>> On 12/08/2015 06:29 AM, Cedric VONCKEN wrote:
>>>>>>>>>
>>>>>>>>>      I'm testing to transmit frame with 802.1q tag (VLAN).
>>>>>>>>>
>>>>>>>>>      My client is set in STA + WDS and the netdev is bridged 
>>>>>>>>> with eth0.
>>>>>>>>>      I have a computer with vlan configuration set connected 
>>>>>>>>> to the STA
>>>>>>>>> eth0.
>>>>>>>>>
>>>>>>>>>      If I try to transmit frames with 802.1q tag, the frames 
>>>>>>>>> are not
>>>>>>>
>>>>>>> sent.
>>>>>>>>>
>>>>>>>>>      I checked with wireless sniffer, and I don't see the 
>>>>>>>>> frame with
>>>>>>>>> VLAN
>>>>>>>>> tag (the frames without VLAN tag are sent).
>>>>>>>>>
>>>>>>>>>      I tested with firmware 10.2.4.70.14-2 from kale github,
>>>>>>>>> 10.1.467-ct-com-full-015 from candelatech and 10.2.4.70-2 from
>>>>>>>>> openwrt, and in all cases I have the same issue.
>>>>>>>>>
>>>>>>>>>      Thanks for your help.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -- 
>>>>>>>>> To unsubscribe from this list: send the line "unsubscribe
>>>>>>>>> linux-wireless" in the body of a message to 
>>>>>>>>> majordomo@vger.kernel.org
>>>>>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>>>>>>
>>>>>>>> -- 
>>>>>>>> Ben Greear <greearb@candelatech.com>
>>>>>>>> Candela Technologies Inc  http://www.candelatech.com
>>>>>>>
>>>>>>> -- 
>>>>>>> To unsubscribe from this list: send the line "unsubscribe 
>>>>>>> linux-wireless"
>>>>>>> in
>>>>>>> the body of a message to majordomo@vger.kernel.org
>>>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>>>
>>>>>> _______________________________________________
>>>>>> openwrt-devel mailing list
>>>>>> openwrt-devel@lists.openwrt.org
>>>>>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>>>>>
>>>>> _______________________________________________
>>>>> openwrt-devel mailing list
>>>>> openwrt-devel@lists.openwrt.org
>>>>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>>>>
>>>> _______________________________________________
>>>> ath10k mailing list
>>>> ath10k@lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/ath10k
>>>
>>
>>
>
>


-- 
Mit freundlichen Grüssen / Regards

Sebastian Gottschall / CTO

NewMedia-NET GmbH - DD-WRT
Firmensitz:  Berliner Ring 101, 64625 Bensheim
Registergericht: Amtsgericht Darmstadt, HRB 25473
Geschäftsführer: Peter Steinhäuser, Christian Scheele
http://www.dd-wrt.com
email: s.gottschall@dd-wrt.com
Tel.: +496251-582650 / Fax: +496251-5826565

^ permalink raw reply

* Re: [PATCH 04/10] rt2800: do not overwrite WPDMA_GLO_CFG_WP_DMA_BURST_SIZE
From: Mathias Kresin @ 2016-11-05 12:55 UTC (permalink / raw)
  To: Stanislaw Gruszka, linux-wireless; +Cc: Helmut Schaa
In-Reply-To: <1478095865-8651-5-git-send-email-sgruszka@redhat.com>

02.11.2016 15:10, Stanislaw Gruszka:
> We already initlized WPDMA_GLO_CFG_WP_DMA_BURST_SIZE to 3 on
> rt2800_init_registers().
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
>  drivers/net/wireless/ralink/rt2x00/rt2800lib.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> index feceb13..9ecdc4c 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> @@ -6756,7 +6756,6 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
>  	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
>  	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
>  	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
> -	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);

More a notice than a potential issue since I don't have much knowledge 
about the driver/chip internals.

But WPDMA_GLO_CFG_WP_DMA_BURST_SIZE in rt2800_init_registers() is set 
conditionally for rt2x00_is_usb(rt2x00dev), where this one is set 
unconditionally. Not sure if this change has side effects.

Mathias

^ permalink raw reply

* Re: [PATCH 05/10] rt2800: make ba_size depend on ampdu_factor
From: Mathias Kresin @ 2016-11-05 12:56 UTC (permalink / raw)
  To: Stanislaw Gruszka, linux-wireless; +Cc: Helmut Schaa
In-Reply-To: <1478095865-8651-6-git-send-email-sgruszka@redhat.com>

02.11.2016 15:11, Stanislaw Gruszka:
> We can calculate BA window size (max number of pending frames not
> yet block acked) of remote station using Maximum A-MPDU length factor
> for that station.
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
>  drivers/net/wireless/ralink/rt2x00/rt2x00queue.c |   15 ++++++++++-----
>  1 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
> index 68b620b..9da89e3 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
> @@ -305,14 +305,19 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
>  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
>  	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
>  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> -	struct rt2x00_sta *sta_priv = NULL;
> +	u8 ba_size = 0;
>
>  	if (sta) {
> -		txdesc->u.ht.mpdu_density =
> -		    sta->ht_cap.ampdu_density;
> +		struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
>
> -		sta_priv = sta_to_rt2x00_sta(sta);
> +		txdesc->u.ht.mpdu_density = sta->ht_cap.ampdu_density;
>  		txdesc->u.ht.wcid = sta_priv->wcid;
> +
> +		if (!(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) {
> +			ba_size = IEEE80211_MIN_AMPDU_BUF;
> +			ba_size <<= sta->ht_cap.ampdu_factor;
> +			ba_size = min_t(int, 63, ba_size - 1);
> +		}
>  	}
>
>  	/*
> @@ -345,7 +350,7 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
>  		return;
>  	}
>
> -	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
> +	txdesc->u.ht.ba_size = ba_size;
>
>  	/*
>  	 * Only one STBC stream is supported for now.
>

Having this patch applied, the throughput on a vgv7510kw22 (RT3062F) in 
AP mode using LEDE head is decreased by somewhat around 10 Mbits/sec. 
I'm using iperf3 for throughput tests and having this patch reverted the 
throughout is back to 80 Mbits/sec.

When bringing down the wifi interface the following messages are logged 
with the patch applied:

[  281.738373] ieee80211 phy0: rt2x00queue_flush_queue: Warning - Queue 
2 failed to flush
[  281.906380] ieee80211 phy0: rt2x00queue_flush_queue: Warning - Queue 
2 failed to flush

Mathias

^ permalink raw reply

* Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: Ben Greear @ 2016-11-05 14:35 UTC (permalink / raw)
  To: Sebastian Gottschall, yu-chieh kung, Bruno Antunes
  Cc: Mauro Mozzarelli, linux-wireless@vger.kernel.org,
	OpenWrt Development List, ath10k@lists.infradead.org
In-Reply-To: <846c145b-3b15-45ca-249a-040518bc2dad@dd-wrt.com>

Looks to me like 10.4 defaults to the right value, but possibly there are other
issues with it.  I tested my CT 10.4 and it worked OK with vlans for me.

Thanks,
Ben

On 11/05/2016 01:05 AM, Sebastian Gottschall wrote:
> would be good if qca can fix this bug finally in all available firmwares. its a very annoying issue since a long time
>
> Sebastian
>
>
> Am 04.11.2016 um 23:23 schrieb Ben Greear:
>> The bug appears that vlan-tx-stripping is unconditionally enabled in
>> at least my firmware.  I have re-compiled w/out that flag set, and it appears
>> to work for me.
>>
>> Please download this firmware, rename it firmware-2.bin, make sure you remove/rename
>> any firmware-5.bin (etc) so mine will load, and see if that fixes your problem.
>>
>> Please note that it is very likely you will have to use same MAC address
>> for the VLAN devices that the underlying station uses in order for this to work.
>>
>> https://www.candelatech.com/downloads/tmp/firmware-2-full-community.bin
>>
>>
>> Thanks,
>> Ben
>>
>>
>> On 11/04/2016 02:50 PM, Ben Greear wrote:
>>> I can reproduce this in my CT firmware. I'll see if I can fix it,
>>> but for stock firmware, it might be that changing the driver to use Ethernet packet type
>>> of native-wifi would make .1q vlans work.
>>>
>>> Thanks,
>>> Ben
>>>
>>> On 11/04/2016 10:28 AM, yu-chieh kung wrote:
>>>> I met the same problem before,
>>>> if i modify the 1q header to other value (0xaa00) before go into firmware.
>>>> I can capture the packet in the air
>>>> I think the vlan packet is dropped in firmware.
>>>>
>>>> 2016-11-04 22:41 GMT+08:00 Bruno Antunes <baantunes@gmail.com>:
>>>>> On 4 November 2016 at 14:18, Mauro Mozzarelli <openwrt@ezplanet.net> wrote:
>>>>>> Since the capability is implemented in software you might be testing the
>>>>>> limit of your router's CPU i/o speed.
>>>>>
>>>>> By loading the module in rawmode?
>>>>>
>>>>> The AP is an APU and Sta is an APU2.
>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 04/11/16 14:13, Bruno Antunes wrote:
>>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> Old thread but I think the issue is still present.
>>>>>>>
>>>>>>> I'm running a setup with VLANs with WDS and ath10k cards.
>>>>>>>
>>>>>>> To make it work both cards must be loaded in rawmode, AP
>>>>>>> and Sta, and with no security.
>>>>>>>
>>>>>>> I'm using a OpenWrt trunk r49941 and the most recent firmware,
>>>>>>> 10.2.4.70.58, from Kalle ath10k firmware tree.
>>>>>>>
>>>>>>> Although it works the throughput is very bad.
>>>>>>> Are there any alternatives to improve the throughput.
>>>>>>>
>>>>>>> Best Regards,
>>>>>>> Bruno
>>>>>>>
>>>>>>> On 9 December 2015 at 17:24, voncken <cedric.voncken@acksys.fr> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>> -----Message d'origine-----
>>>>>>>>> De : Ben Greear [mailto:greearb@candelatech.com]
>>>>>>>>> Envoyé : mercredi 9 décembre 2015 16:34
>>>>>>>>> À : Cedric VONCKEN; ath10k@lists.infradead.org; linux-wireless
>>>>>>>>> Objet : Re: ATH10K VLAN firmware issue
>>>>>>>>>
>>>>>>>>> This only happens when you use STA  + WDS, or is .1q broken for you in
>>>>>>>>> other cases as well?
>>>>>>>>
>>>>>>>> No, this issue occurs in all modes (STA, STA + WDS, AP).
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>>> Cedric.
>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Ben
>>>>>>>>>
>>>>>>>>> On 12/08/2015 06:29 AM, Cedric VONCKEN wrote:
>>>>>>>>>>
>>>>>>>>>>      I'm testing to transmit frame with 802.1q tag (VLAN).
>>>>>>>>>>
>>>>>>>>>>      My client is set in STA + WDS and the netdev is bridged with eth0.
>>>>>>>>>>      I have a computer with vlan configuration set connected to the STA
>>>>>>>>>> eth0.
>>>>>>>>>>
>>>>>>>>>>      If I try to transmit frames with 802.1q tag, the frames are not
>>>>>>>>
>>>>>>>> sent.
>>>>>>>>>>
>>>>>>>>>>      I checked with wireless sniffer, and I don't see the frame with
>>>>>>>>>> VLAN
>>>>>>>>>> tag (the frames without VLAN tag are sent).
>>>>>>>>>>
>>>>>>>>>>      I tested with firmware 10.2.4.70.14-2 from kale github,
>>>>>>>>>> 10.1.467-ct-com-full-015 from candelatech and 10.2.4.70-2 from
>>>>>>>>>> openwrt, and in all cases I have the same issue.
>>>>>>>>>>
>>>>>>>>>>      Thanks for your help.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> To unsubscribe from this list: send the line "unsubscribe
>>>>>>>>>> linux-wireless" in the body of a message to majordomo@vger.kernel.org
>>>>>>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Ben Greear <greearb@candelatech.com>
>>>>>>>>> Candela Technologies Inc  http://www.candelatech.com
>>>>>>>>
>>>>>>>> --
>>>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-wireless"
>>>>>>>> in
>>>>>>>> the body of a message to majordomo@vger.kernel.org
>>>>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> openwrt-devel mailing list
>>>>>>> openwrt-devel@lists.openwrt.org
>>>>>>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>>>>>>
>>>>>> _______________________________________________
>>>>>> openwrt-devel mailing list
>>>>>> openwrt-devel@lists.openwrt.org
>>>>>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>>>>>
>>>>> _______________________________________________
>>>>> ath10k mailing list
>>>>> ath10k@lists.infradead.org
>>>>> http://lists.infradead.org/mailman/listinfo/ath10k
>>>>
>>>
>>>
>>
>>
>
>

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* [PATCH] ssb: Fix error routine when fallback SPROM fails
From: Larry Finger @ 2016-11-05 19:08 UTC (permalink / raw)
  To: kvalo; +Cc: devel, linux-wireless, Larry Finger, Stable

When there is a CRC error in the SPROM read from the device, the code
attempts to handle a fallback SPROM. When this also fails, the driver
returns zero rather than an error code.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
---
 drivers/ssb/pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 0f28c08..77b551d 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -909,6 +909,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
 			if (err) {
 				ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
 					 err);
+				goto out_free;
 			} else {
 				ssb_dbg("Using SPROM revision %d provided by platform\n",
 					sprom->revision);
-- 
2.10.0

^ permalink raw reply related

* [PATCH 0/3][RFC] CQM RSSI event with many thresholds
From: Andrew Zaborowski @ 2016-11-06  2:08 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Andrew Zaborowski <balrogg@gmail.com>

This is a first stab at a nl80211 API using multiple RSSI thresholds
discussed previously.  It is similar to the current CQM RSSI event with
one threshold and a hysteresis parameter.  I tried to avoid creating
new nl80211 commands and events so I extended the existing command.
There's still a NL80211_ATTR_CQM_RSSI_THOLD attribute and a hysteresis
attribute but multiple thresholds can be supplied as an array.

All this is a proposal and open to changes.

There are two different mechanisms for compatibility with the current
behavior in which events are generated every time the RSSI value is
more than $hysteresis dBm away from the last event's level, even if
$threshold wasn't crossed.  For example with the rssi going up from 20dBm
and the threshold set at 40 and hysteresis at 5, there'll be events at
40, 45, 50 and so on.  I assume this is intentional because most
drivers replicate this behavior.  If 2 or more thresholds are supplied
in NL80211_ATTR_CQM_RSSI_THOLD (i.e. it is not 4 byte long) this will
enable the new mechanism and events are only generated when a threshold
is crossed.

My opinion is that the new mechanism is similar enough to the current
one that it would be best if each driver didn't have to implement both
mechanisms, and one could be a special case of the other.  However I
can't update all drivers because I can't test them.  So at the driver
level there have to be two methods until all drivers implement the
new method (set_cqm_rssi_range_config, which uses a low and a high
threshold) and the current behavior can be implemented on to of it.
So the next best thing is that at least the netlink API can present it
as a single interface.  Also both mechanisms never have to be enabled
simultaneously, the driver doesn't have to support them both at the
same time.

Also it seems that the wl1271 (wlcore) driver can offload RSSI
monitoring to hardware using exactly the two parameters used today:
one threshold and a hysteresis value, and no other mechanism is
supported by the hardware, so it wouldn't make sense for it to drop
the current method.

Andrew Zaborowski (3):
  mac80211: Pass new RSSI level in CQM RSSI notification
  cfg80211: Pass new RSSI level in CQM RSSI notification
  nl80211/mac80211: Accept multiple RSSI thresholds for CQM

 drivers/net/wireless/intel/iwlwifi/mvm/rx.c      |   2 +
 drivers/net/wireless/marvell/mwifiex/sta_event.c |   4 +-
 drivers/net/wireless/rndis_wlan.c                |   2 +-
 drivers/net/wireless/rsi/rsi_91x_mac80211.c      |   2 +-
 drivers/net/wireless/st/cw1200/sta.c             |   2 +-
 drivers/net/wireless/ti/wl1251/event.c           |   4 +-
 drivers/net/wireless/ti/wlcore/event.c           |   3 +-
 include/net/cfg80211.h                           |  15 ++-
 include/net/mac80211.h                           |   8 ++
 include/uapi/linux/nl80211.h                     |   7 +-
 net/mac80211/cfg.c                               |  28 +++++
 net/mac80211/mlme.c                              |  33 ++++-
 net/mac80211/trace.h                             |  11 +-
 net/wireless/core.c                              |  13 ++
 net/wireless/core.h                              |   9 ++
 net/wireless/nl80211.c                           | 146 +++++++++++++++++++++--
 net/wireless/rdev-ops.h                          |  12 ++
 net/wireless/trace.h                             |  33 ++++-
 18 files changed, 299 insertions(+), 35 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/3][RFC] mac80211: Pass new RSSI level in CQM RSSI notification
From: Andrew Zaborowski @ 2016-11-06  2:08 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <1478398113-14966-1-git-send-email-andrew.zaborowski@intel.com>

---
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c |  2 ++
 drivers/net/wireless/rsi/rsi_91x_mac80211.c |  2 +-
 drivers/net/wireless/st/cw1200/sta.c        |  2 +-
 drivers/net/wireless/ti/wl1251/event.c      |  4 ++--
 drivers/net/wireless/ti/wlcore/event.c      |  3 ++-
 include/net/mac80211.h                      |  2 ++
 net/mac80211/mlme.c                         |  7 ++++---
 net/mac80211/trace.h                        | 11 +++++++----
 8 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 0e60e38..e06a2e3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -571,6 +571,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
 		ieee80211_cqm_rssi_notify(
 			vif,
 			NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+			sig,
 			GFP_KERNEL);
 	} else if (sig > thold &&
 		   (last_event == 0 || sig > last_event + hyst)) {
@@ -580,6 +581,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
 		ieee80211_cqm_rssi_notify(
 			vif,
 			NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+			sig,
 			GFP_KERNEL);
 	}
 }
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index dbb2389..3e260b4 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -818,7 +818,7 @@ static void rsi_perform_cqm(struct rsi_common *common,
 
 	common->cqm_info.last_cqm_event_rssi = rssi;
 	rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
-	ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL);
+	ieee80211_cqm_rssi_notify(adapter->vifs[0], event, rssi, GFP_KERNEL);
 
 	return;
 }
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c
index daf06a4..a522248 100644
--- a/drivers/net/wireless/st/cw1200/sta.c
+++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -1019,7 +1019,7 @@ void cw1200_event_handler(struct work_struct *work)
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW :
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
 			pr_debug("[CQM] RSSI event: %d.\n", rcpi_rssi);
-			ieee80211_cqm_rssi_notify(priv->vif, cqm_evt,
+			ieee80211_cqm_rssi_notify(priv->vif, cqm_evt, rcpi_rssi,
 						  GFP_KERNEL);
 			break;
 		}
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index d0593bc..f5acd24 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -150,7 +150,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 				     "ROAMING_TRIGGER_LOW_RSSI_EVENT");
 			ieee80211_cqm_rssi_notify(wl->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-				GFP_KERNEL);
+				0, GFP_KERNEL);
 		}
 
 		if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
@@ -158,7 +158,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 				     "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
 			ieee80211_cqm_rssi_notify(wl->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-				GFP_KERNEL);
+				0, GFP_KERNEL);
 		}
 	}
 
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 4b59f67..f2e90d2 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -129,7 +129,8 @@ void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr)
 
 		vif = wl12xx_wlvif_to_vif(wlvif);
 		if (event != wlvif->last_rssi_event)
-			ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL);
+			ieee80211_cqm_rssi_notify(vif, event, metric,
+						  GFP_KERNEL);
 		wlvif->last_rssi_event = event;
 	}
 }
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a810dfc..33026e1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -5244,6 +5244,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  * @rssi_event: the RSSI trigger event type
+ * @rssi_level: new RSSI level value or 0 if not available
  * @gfp: context flags
  *
  * When the %IEEE80211_VIF_SUPPORTS_CQM_RSSI is set, and a connection quality
@@ -5252,6 +5253,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
  */
 void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 			       enum nl80211_cqm_rssi_threshold_event rssi_event,
+			       s32 rssi_level,
 			       gfp_t gfp);
 
 /**
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7486f2d..a55cdd7 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3405,14 +3405,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 			ieee80211_cqm_rssi_notify(
 				&sdata->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-				GFP_KERNEL);
+				sig, GFP_KERNEL);
 		} else if (sig > thold &&
 			   (last_event == 0 || sig > last_event + hyst)) {
 			ifmgd->last_cqm_event_signal = sig;
 			ieee80211_cqm_rssi_notify(
 				&sdata->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-				GFP_KERNEL);
+				sig, GFP_KERNEL);
 		}
 	}
 
@@ -5000,11 +5000,12 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 
 void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 			       enum nl80211_cqm_rssi_threshold_event rssi_event,
+			       s32 rssi_level,
 			       gfp_t gfp)
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
-	trace_api_cqm_rssi_notify(sdata, rssi_event);
+	trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level);
 
 	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
 }
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 92a47af..f78d9f4 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1996,23 +1996,26 @@ TRACE_EVENT(api_connection_loss,
 
 TRACE_EVENT(api_cqm_rssi_notify,
 	TP_PROTO(struct ieee80211_sub_if_data *sdata,
-		 enum nl80211_cqm_rssi_threshold_event rssi_event),
+		 enum nl80211_cqm_rssi_threshold_event rssi_event,
+		 s32 rssi_level),
 
-	TP_ARGS(sdata, rssi_event),
+	TP_ARGS(sdata, rssi_event, rssi_level),
 
 	TP_STRUCT__entry(
 		VIF_ENTRY
 		__field(u32, rssi_event)
+		__field(s32, rssi_level)
 	),
 
 	TP_fast_assign(
 		VIF_ASSIGN;
 		__entry->rssi_event = rssi_event;
+		__entry->rssi_level = rssi_level;
 	),
 
 	TP_printk(
-		VIF_PR_FMT " event:%d",
-		VIF_PR_ARG, __entry->rssi_event
+		VIF_PR_FMT " event:%d rssi:%d",
+		VIF_PR_ARG, __entry->rssi_event, __entry->rssi_level
 	)
 );
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/3][RFC] cfg80211: Pass new RSSI level in CQM RSSI notification
From: Andrew Zaborowski @ 2016-11-06  2:08 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <1478398113-14966-1-git-send-email-andrew.zaborowski@intel.com>

Update the drivers to pass the RSSI level as a cfg80211_cqm_rssi_notify
parameter and pass this value to userspace in a new nl80211 attribute.
This helps both userspace and also helps in the implementation of the
multiple RSSI thresholds CQM mechanism.

Note for marvell/mwifiexe I pass 0 for the RSSI value because the new
RSSI value is not available to the driver at the time of the
cfg80211_cqm_rssi_notify call, but the driver queries the new value
immediately after that, so it is actually available just a moment later
if we wanted to defer caling cfg80211_cqm_rssi_notify until that moment.
Without this, the new cfg80211 code (patch 3) will call .get_station
which will send a duplicate HostCmd_CMD_RSSI_INFO command to the hardware.
---
 drivers/net/wireless/marvell/mwifiex/sta_event.c |  4 ++--
 drivers/net/wireless/rndis_wlan.c                |  2 +-
 include/net/cfg80211.h                           |  3 ++-
 include/uapi/linux/nl80211.h                     |  3 +++
 net/mac80211/mlme.c                              |  2 +-
 net/wireless/nl80211.c                           |  9 +++++++--
 net/wireless/trace.h                             | 11 +++++++----
 7 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index 9df0c4d..5cc3aa7 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -824,7 +824,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 	case EVENT_RSSI_LOW:
 		cfg80211_cqm_rssi_notify(priv->netdev,
 					 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-					 GFP_KERNEL);
+					 0, GFP_KERNEL);
 		mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
 				 HostCmd_ACT_GEN_GET, 0, NULL, false);
 		priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
@@ -839,7 +839,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 	case EVENT_RSSI_HIGH:
 		cfg80211_cqm_rssi_notify(priv->netdev,
 					 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-					 GFP_KERNEL);
+					 0, GFP_KERNEL);
 		mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
 				 HostCmd_ACT_GEN_GET, 0, NULL, false);
 		priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 603c904..785334f 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -3187,7 +3187,7 @@ static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi)
 		return;
 
 	priv->last_cqm_event_rssi = rssi;
-	cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL);
+	cfg80211_cqm_rssi_notify(usbdev->net, event, rssi, GFP_KERNEL);
 }
 
 #define DEVICE_POLLER_JIFFIES (HZ)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bd19faa..632dce1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5167,6 +5167,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
  * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
  * @dev: network device
  * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
  * @gfp: context flags
  *
  * This function is called when a configured connection quality monitoring
@@ -5174,7 +5175,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
  */
 void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
-			      gfp_t gfp);
+			      s32 rssi_level, gfp_t gfp);
 
 /**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 56368e9..48108fd 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3859,6 +3859,8 @@ enum nl80211_ps_state {
  *	%NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.
  * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon
  *	loss event
+ * @NL80211_ATTR_CQM_RSSI_LEVEL: the RSSI value in dBm that triggered the
+ *	RSSI threshold event.
  * @__NL80211_ATTR_CQM_AFTER_LAST: internal
  * @NL80211_ATTR_CQM_MAX: highest key attribute
  */
@@ -3872,6 +3874,7 @@ enum nl80211_attr_cqm {
 	NL80211_ATTR_CQM_TXE_PKTS,
 	NL80211_ATTR_CQM_TXE_INTVL,
 	NL80211_ATTR_CQM_BEACON_LOSS_EVENT,
+	NL80211_ATTR_CQM_RSSI_LEVEL,
 
 	/* keep last */
 	__NL80211_ATTR_CQM_AFTER_LAST,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a55cdd7..6898ecb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -5007,7 +5007,7 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 
 	trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level);
 
-	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
+	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, rssi_level, gfp);
 }
 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c510810..5d10774 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9278,6 +9278,7 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
 	[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
+	[NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
 };
 
 static int nl80211_set_cqm_txe(struct genl_info *info,
@@ -13737,11 +13738,11 @@ static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
 
 void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
-			      gfp_t gfp)
+			      s32 rssi_level, gfp_t gfp)
 {
 	struct sk_buff *msg;
 
-	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+	trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
 
 	if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
 		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
@@ -13755,6 +13756,10 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			rssi_event))
 		goto nla_put_failure;
 
+	if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
+				      rssi_level))
+		goto nla_put_failure;
+
 	cfg80211_send_cqm(msg, gfp);
 
 	return;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a3d0a91..6ac46a0 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2472,18 +2472,21 @@ TRACE_EVENT(cfg80211_mgmt_tx_status,
 
 TRACE_EVENT(cfg80211_cqm_rssi_notify,
 	TP_PROTO(struct net_device *netdev,
-		 enum nl80211_cqm_rssi_threshold_event rssi_event),
-	TP_ARGS(netdev, rssi_event),
+		 enum nl80211_cqm_rssi_threshold_event rssi_event,
+		 s32 rssi_level),
+	TP_ARGS(netdev, rssi_event, rssi_level),
 	TP_STRUCT__entry(
 		NETDEV_ENTRY
 		__field(enum nl80211_cqm_rssi_threshold_event, rssi_event)
+		__field(s32, rssi_level)
 	),
 	TP_fast_assign(
 		NETDEV_ASSIGN;
 		__entry->rssi_event = rssi_event;
+		__entry->rssi_level = rssi_level;
 	),
-	TP_printk(NETDEV_PR_FMT ", rssi event: %d",
-		  NETDEV_PR_ARG, __entry->rssi_event)
+	TP_printk(NETDEV_PR_FMT ", rssi event: %d, level: %d",
+		  NETDEV_PR_ARG, __entry->rssi_event, __entry->rssi_level)
 );
 
 TRACE_EVENT(cfg80211_reg_can_beacon,
-- 
2.7.4

^ permalink raw reply related

* [PATCH 3/3][RFC] nl80211/mac80211: Accept multiple RSSI thresholds for CQM
From: Andrew Zaborowski @ 2016-11-06  2:08 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <1478398113-14966-1-git-send-email-andrew.zaborowski@intel.com>

Change the SET CQM command RSSI threshold attribute semantic to accept
any number of thresholds as a sorted array.  The API should be backwards
compatible so that if one s32 threshold value is passed, the old
mechanism is enabled.  The netlink event generated is the same too.

cfg80211 handles an arbitrary number of RSSI thresholds but drivers have
to provide a method (set_cqm_rssi_range_config) that configures a range
set by a high and a low value.  Drivers have to call back when the RSSI
goes out of that range and there's no additional event every time the
range is reconfigured.  There's no reason that the whole mechanism with
more than 2 thresholds couldn't be offloaded if the was hardware
available.

I added only a mac80211 implementation of the set_cqm_rssi_range_config
method as an illustration and because I can't run-time test any other
driver.  In this patch there's also no API for mac80211-based drivers
that do beacon filtering to offload this but that would be the intended
use.
---
 include/net/cfg80211.h       |  12 ++++
 include/net/mac80211.h       |   6 ++
 include/uapi/linux/nl80211.h |   4 +-
 net/mac80211/cfg.c           |  28 +++++++++
 net/mac80211/mlme.c          |  24 ++++++++
 net/wireless/core.c          |  13 ++++
 net/wireless/core.h          |   9 +++
 net/wireless/nl80211.c       | 137 +++++++++++++++++++++++++++++++++++++++----
 net/wireless/rdev-ops.h      |  12 ++++
 net/wireless/trace.h         |  22 +++++++
 10 files changed, 255 insertions(+), 12 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 632dce1..0105e86 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2604,6 +2604,10 @@ struct cfg80211_nan_func {
  *	the current level is above/below the configured threshold; this may
  *	need some care when the configuration is changed (without first being
  *	disabled.)
+ * @set_cqm_rssi_range_config: Configure two RSSI thresholds in the
+ *	connection quality monitor.  Even if the driver implements both the
+ *	single threshold and low/high thresholds mechanisms, it should assume
+ *	only one is active at any time.
  * @set_cqm_txe_config: Configure connection quality monitor TX error
  *	thresholds.
  * @sched_scan_start: Tell the driver to start a scheduled scan.
@@ -2887,6 +2891,10 @@ struct cfg80211_ops {
 				       struct net_device *dev,
 				       s32 rssi_thold, u32 rssi_hyst);
 
+	int	(*set_cqm_rssi_range_config)(struct wiphy *wiphy,
+					     struct net_device *dev,
+					     s32 rssi_low, s32 rssi_high);
+
 	int	(*set_cqm_txe_config)(struct wiphy *wiphy,
 				      struct net_device *dev,
 				      u32 rate, u32 pkts, u32 intvl);
@@ -3709,6 +3717,7 @@ void wiphy_free(struct wiphy *wiphy);
 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
+struct cfg80211_cqm_config;
 
 /**
  * struct wireless_dev - wireless device state
@@ -3769,6 +3778,7 @@ struct cfg80211_cached_keys;
  * @event_list: (private) list for internal event processing
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
+ * @cqm_config: (private) nl80211 RSSI monitor state
  */
 struct wireless_dev {
 	struct wiphy *wiphy;
@@ -3833,6 +3843,8 @@ struct wireless_dev {
 		bool prev_bssid_valid;
 	} wext;
 #endif
+
+	struct cfg80211_cqm_config *cqm_config;
 };
 
 static inline u8 *wdev_address(struct wireless_dev *wdev)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 33026e1..7da1056 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -502,6 +502,10 @@ struct ieee80211_mu_group_data {
  *	implies disabled. As with the cfg80211 callback, a change here should
  *	cause an event to be sent indicating where the current value is in
  *	relation to the newly configured threshold.
+ * @cqm_rssi_low: Connection quality monitor RSSI lower threshold, a zero value
+ *	implies disabled.  This is an alternative mechanism to the single
+ *	threshold event and can't be enabled simultaneously.
+ * @cqm_rssi_low: Connection quality monitor RSSI upper threshold.
  * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
  * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
  *	may filter ARP queries targeted for other addresses than listed here.
@@ -554,6 +558,8 @@ struct ieee80211_bss_conf {
 	u16 ht_operation_mode;
 	s32 cqm_rssi_thold;
 	u32 cqm_rssi_hyst;
+	s32 cqm_rssi_low;
+	s32 cqm_rssi_high;
 	struct cfg80211_chan_def chandef;
 	struct ieee80211_mu_group_data mu_group;
 	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 48108fd..d632c6a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3839,7 +3839,9 @@ enum nl80211_ps_state {
  * @__NL80211_ATTR_CQM_INVALID: invalid
  * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies
  *	the threshold for the RSSI level at which an event will be sent. Zero
- *	to disable.
+ *	to disable.  Alternatively multiple values can be supplied as a
+ *	low-to-high sorted array of thresholds in dBm.  Events will be sent
+ *	when the RSSI value crosses any of the thresholds.
  * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies
  *	the minimum amount the RSSI level must change after an event before a
  *	new event may be issued (to reduce effects of RSSI oscillation).
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fd6541f..6ac0523 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2647,6 +2647,33 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 
 	bss_conf->cqm_rssi_thold = rssi_thold;
 	bss_conf->cqm_rssi_hyst = rssi_hyst;
+	bss_conf->cqm_rssi_low = 0;
+	bss_conf->cqm_rssi_high = 0;
+	sdata->u.mgd.last_cqm_event_signal = 0;
+
+	/* tell the driver upon association, unless already associated */
+	if (sdata->u.mgd.associated &&
+	    sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
+		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+
+	return 0;
+}
+
+static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
+					       struct net_device *dev,
+					       s32 rssi_low, s32 rssi_high)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_vif *vif = &sdata->vif;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
+		return -EOPNOTSUPP;
+
+	bss_conf->cqm_rssi_low = rssi_low;
+	bss_conf->cqm_rssi_high = rssi_high;
+	bss_conf->cqm_rssi_thold = 0;
+	bss_conf->cqm_rssi_hyst = 0;
 	sdata->u.mgd.last_cqm_event_signal = 0;
 
 	/* tell the driver upon association, unless already associated */
@@ -3645,6 +3672,7 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.mgmt_tx = ieee80211_mgmt_tx,
 	.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
 	.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
+	.set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
 	.mgmt_frame_register = ieee80211_mgmt_frame_register,
 	.set_antenna = ieee80211_set_antenna,
 	.get_antenna = ieee80211_get_antenna,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6898ecb..7f99918 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3416,6 +3416,30 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 		}
 	}
 
+	if (bss_conf->cqm_rssi_low &&
+	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
+		int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
+		int last_event = ifmgd->last_cqm_event_signal;
+		int low = bss_conf->cqm_rssi_low;
+		int high = bss_conf->cqm_rssi_high;
+
+		if (sig < low &&
+		    (last_event == 0 || last_event >= low)) {
+			ifmgd->last_cqm_event_signal = sig;
+			ieee80211_cqm_rssi_notify(
+				&sdata->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+				sig, GFP_KERNEL);
+		} else if (sig > high &&
+			   (last_event == 0 || last_event <= high)) {
+			ifmgd->last_cqm_event_signal = sig;
+			ieee80211_cqm_rssi_notify(
+				&sdata->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+				sig, GFP_KERNEL);
+		}
+	}
+
 	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
 		mlme_dbg_ratelimited(sdata,
 				     "cancelling AP probe due to a received beacon\n");
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d..f6c1bf2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -928,6 +928,16 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
 
+void cfg80211_cqm_config_free(struct wireless_dev *wdev)
+{
+	if (!wdev->cqm_config)
+		return;
+
+	kfree(wdev->cqm_config->rssi_thresholds);
+	kfree(wdev->cqm_config);
+	wdev->cqm_config = NULL;
+}
+
 void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
@@ -954,6 +964,8 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 		WARN_ON_ONCE(1);
 		break;
 	}
+
+	cfg80211_cqm_config_free(wdev);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
 
@@ -1205,6 +1217,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 #ifdef CONFIG_CFG80211_WEXT
 			kzfree(wdev->wext.keys);
 #endif
+			cfg80211_cqm_config_free(wdev);
 		}
 		/*
 		 * synchronise (so that we won't find this netdev
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 08d2e94..75fc334 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -270,6 +270,13 @@ struct cfg80211_iface_destroy {
 	u32 nlportid;
 };
 
+struct cfg80211_cqm_config {
+	s32 *rssi_thresholds;
+	int n_rssi_thresholds;
+	u32 rssi_hyst;
+	s32 last_rssi_event_value;
+};
+
 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
 
 /* free object */
@@ -504,4 +511,6 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
 #define CFG80211_DEV_WARN_ON(cond)	({bool __r = (cond); __r; })
 #endif
 
+void cfg80211_cqm_config_free(struct wireless_dev *wdev);
+
 #endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5d10774..907bd2a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9272,7 +9272,7 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
 
 static const struct nla_policy
 nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
-	[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
+	[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
 	[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
@@ -9301,28 +9301,127 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
 	return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
 }
 
+static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
+				    struct net_device *dev)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	s32 last, low, high;
+	u32 hyst;
+	int i, n;
+	int err;
+
+	/* RSSI reporting disabled? */
+	if (!wdev->cqm_config)
+		return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
+
+	/*
+	 * Obtain current RSSI value if possible, if not and no RSSI threshold
+	 * event has been received yet, we should receive an event after a
+	 * connection is established and enough beacons received to calculate
+	 * the average.
+	 */
+	if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss) {
+		struct station_info sinfo;
+		u8 *mac_addr;
+
+		mac_addr = wdev->current_bss->pub.bssid;
+
+		err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
+		if (err)
+			return err;
+
+		if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
+			wdev->cqm_config->last_rssi_event_value =
+				(s8) sinfo.rx_beacon_signal_avg;
+	}
+
+	last = wdev->cqm_config->last_rssi_event_value;
+	hyst = wdev->cqm_config->rssi_hyst;
+	n = wdev->cqm_config->n_rssi_thresholds;
+
+	for (i = 0; i < n; i++)
+		if (last < wdev->cqm_config->rssi_thresholds[i])
+			break;
+
+	low = i > 0 ? wdev->cqm_config->rssi_thresholds[i - 1] : S32_MIN;
+	high = i < n ? wdev->cqm_config->rssi_thresholds[i] : S32_MAX;
+
+	if (low > (s32) (last - hyst))
+		low = last - hyst;
+	if (high < (s32) (last + hyst))
+		high = last + hyst;
+
+	return rdev_set_cqm_rssi_range_config(rdev, dev, low, high - 1);
+}
+
 static int nl80211_set_cqm_rssi(struct genl_info *info,
-				s32 threshold, u32 hysteresis)
+				const s32 *thresholds, int n_thresholds,
+				u32 hysteresis)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct net_device *dev = info->user_ptr[1];
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	int i, err;
+	s32 prev = S32_MIN;
 
-	if (threshold > 0)
-		return -EINVAL;
+	/* Check all values negative and sorted */
+	for (i = 0; i < n_thresholds; i++) {
+		if (thresholds[i] > 0 || thresholds[i] <= prev)
+			return -EINVAL;
+
+		prev = thresholds[i];
+	}
+
+	if (n_thresholds == 1 && thresholds[0] == 0)
+		n_thresholds = 0;
 
 	/* disabling - hysteresis should also be zero then */
-	if (threshold == 0)
+	if (n_thresholds == 0)
 		hysteresis = 0;
 
-	if (!rdev->ops->set_cqm_rssi_config)
-		return -EOPNOTSUPP;
-
 	if (wdev->iftype != NL80211_IFTYPE_STATION &&
 	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
 		return -EOPNOTSUPP;
 
-	return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis);
+	wdev_lock(wdev);
+	cfg80211_cqm_config_free(wdev);
+	wdev_unlock(wdev);
+
+	if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
+		const s32 disable = 0;
+
+		if (n_thresholds == 0) {
+			n_thresholds = 1;
+			thresholds = &disable;
+		}
+
+		return rdev_set_cqm_rssi_config(rdev, dev,
+						thresholds[0], hysteresis);
+	}
+
+	if (!rdev->ops->set_cqm_rssi_range_config || !rdev->ops->get_station)
+		return -EOPNOTSUPP;
+
+	wdev_lock(wdev);
+	if (n_thresholds) {
+		struct cfg80211_cqm_config *cqm_config;
+
+		cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config),
+					   GFP_KERNEL);
+		cqm_config->rssi_thresholds =
+			kmemdup(thresholds, n_thresholds * sizeof(s32),
+				GFP_KERNEL);
+		cqm_config->n_rssi_thresholds = n_thresholds;
+		cqm_config->rssi_hyst = hysteresis;
+
+		wdev->cqm_config = cqm_config;
+	}
+
+	err = cfg80211_cqm_rssi_update(rdev, dev);
+
+	wdev_unlock(wdev);
+
+	return err;
 }
 
 static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -9342,10 +9441,15 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
 
 	if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
 	    attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
-		s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+		s32 *thresholds = nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+		int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
 		u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
 
-		return nl80211_set_cqm_rssi(info, threshold, hysteresis);
+		if (len % 4)
+			return -EINVAL;
+
+		return nl80211_set_cqm_rssi(info, thresholds, len / 4,
+					    hysteresis);
 	}
 
 	if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
@@ -13741,6 +13845,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      s32 rssi_level, gfp_t gfp)
 {
 	struct sk_buff *msg;
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 
 	trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
 
@@ -13748,6 +13854,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
 		return;
 
+	if (wdev->cqm_config) {
+		wdev->cqm_config->last_rssi_event_value = rssi_level;
+
+		cfg80211_cqm_rssi_update(rdev, dev);
+
+		if (rssi_level == 0)
+			rssi_level = wdev->cqm_config->last_rssi_event_value;
+	}
+
 	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
 	if (!msg)
 		return;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 11cf83c..ae180f3 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -726,6 +726,18 @@ rdev_set_cqm_rssi_config(struct cfg80211_registered_device *rdev,
 }
 
 static inline int
+rdev_set_cqm_rssi_range_config(struct cfg80211_registered_device *rdev,
+			       struct net_device *dev, s32 low, s32 high)
+{
+	int ret;
+	trace_rdev_set_cqm_rssi_range_config(&rdev->wiphy, dev, low, high);
+	ret = rdev->ops->set_cqm_rssi_range_config(&rdev->wiphy, dev,
+						   low, high);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
+static inline int
 rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev,
 			struct net_device *dev, u32 rate, u32 pkts, u32 intvl)
 {
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 6ac46a0..993f661 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1304,6 +1304,28 @@ TRACE_EVENT(rdev_set_cqm_rssi_config,
 		 __entry->rssi_thold, __entry->rssi_hyst)
 );
 
+TRACE_EVENT(rdev_set_cqm_rssi_range_config,
+	TP_PROTO(struct wiphy *wiphy,
+		 struct net_device *netdev, s32 low, s32 high),
+	TP_ARGS(wiphy, netdev, low, high),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__field(s32, rssi_low)
+		__field(s32, rssi_high)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		__entry->rssi_low = low;
+		__entry->rssi_high = high;
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
+		  ", range: %d - %d ",
+		  WIPHY_PR_ARG, NETDEV_PR_ARG,
+		  __entry->rssi_low, __entry->rssi_high)
+);
+
 TRACE_EVENT(rdev_set_cqm_txe_config,
 	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 rate,
 		 u32 pkts, u32 intvl),
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC] rtlwifi: btcoexist: fix port assignment
From: Nicholas Mc Guire @ 2016-11-06 12:56 UTC (permalink / raw)
  To: Larry Finger
  Cc: Chaoming Li, Kalle Valo, Joe Perches, Arnd Bergmann,
	linux-wireless, netdev, linux-kernel, Nicholas Mc Guire

The port assignment in the if case should be to AUX not MAIN.

Fixes: commit baa170229095 ("rtlwifi: btcoexist: Implement antenna selection")
Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
---
problem located by coccinelle

in:
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c:exhalbtc_set_ant_num()
973       /* The antenna position:
974        * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1.
975        * The antenna position should be determined by
976        * auto-detect mechanism.
977        * The following is assumed to main,
978        * and those must be modified
979        * if y auto-detect mechanism is ready
980        */
981       if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
982           (gl_bt_coexist.board_info.btdm_ant_num == 1))
983               gl_bt_coexist.board_info.btdm_ant_pos =
984                                              BTC_ANTENNA_AT_MAIN_PORT;
985       else
986               gl_bt_coexist.board_info.btdm_ant_pos =
987                                              BTC_ANTENNA_AT_MAIN_PORT;
(line number from 4.9.0-rc2 linux-next 20161028)

the if and else branch here are the same but the comment seems to indicate
that the first case should be the AUX port and not the MAIN port here (the
second sentence in the comment though is not really clear to me). If the 
intent is to set it to MAIN unconditionally and then let autodetect fix it
then the if/else construct is useless.

Looks like a cut&past bug, but this needs a check by someone who knows the
details of the device.

Patch was compile tested with: x86_64_defconfig + RTL8723AE=m 
(implies CONFIG_RTLBTCOEXIST)

Patch is against 4.9.0-rc2 (localversion-next is next-20161028)

 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index 91cc139..588c8ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -981,7 +981,7 @@ void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
 		if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
 		    (gl_bt_coexist.board_info.btdm_ant_num == 1))
 			gl_bt_coexist.board_info.btdm_ant_pos =
-						       BTC_ANTENNA_AT_MAIN_PORT;
+						       BTC_ANTENNA_AT_AUX_PORT;
 		else
 			gl_bt_coexist.board_info.btdm_ant_pos =
 						       BTC_ANTENNA_AT_MAIN_PORT;
-- 
2.1.4

^ permalink raw reply related

* Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: Bruno Antunes @ 2016-11-07 11:54 UTC (permalink / raw)
  To: Ben Greear
  Cc: yu-chieh kung, Mauro Mozzarelli, linux-wireless@vger.kernel.org,
	OpenWrt Development List, ath10k@lists.infradead.org
In-Reply-To: <68bd7ebd-b12a-5dbf-a267-5913127718a1@candelatech.com>

On 4 November 2016 at 22:23, Ben Greear <greearb@candelatech.com> wrote:
> The bug appears that vlan-tx-stripping is unconditionally enabled in
> at least my firmware.  I have re-compiled w/out that flag set, and it
> appears
> to work for me.
>
> Please download this firmware, rename it firmware-2.bin, make sure you
> remove/rename
> any firmware-5.bin (etc) so mine will load, and see if that fixes your
> problem.

Thanks for the fast reply but it only solves "half"  the problem.

Now the connection between the AP and the Sta can be secure and the
driver doesn't need to be loaded in rawmode.

Unfortunatly the the throughput is still bad.

iperf3 -c 10.10.4.15
Connecting to host 10.10.4.15, port 5201
[  4] local 10.10.4.16 port 44893 connected to 10.10.4.15 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.01   sec  42.4 KBytes   345 Kbits/sec    6   1.41 KBytes
[  4]   1.01-2.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
[  4]   2.01-3.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
[  4]   3.01-4.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
[  4]   4.01-5.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
[  4]   5.01-6.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
[  4]   6.01-7.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
[  4]   7.01-8.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
[  4]   8.01-9.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
[  4]   9.01-10.01  sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.01  sec  42.4 KBytes  34.7 Kbits/sec    9             sender
[  4]   0.00-10.01  sec  0.00 Bytes  0.00 bits/sec                  receiver

iperf Done.

>
> Please note that it is very likely you will have to use same MAC address
> for the VLAN devices that the underlying station uses in order for this to
> work.

Can you please elaborate more?
My setup  is the folowing.
The connection between the AP and Sta is in WDS
For the moment all devices are in the same VLAN.

client1 --- SW1 ---- AP ...... Sta ---- SW2 --- client2


Thanks,
Bruno

>
> https://www.candelatech.com/downloads/tmp/firmware-2-full-community.bin
>
>
> Thanks,
> Ben
>
>
>

> Ben Greear <greearb@candelatech.com>
> Candela Technologies Inc  http://www.candelatech.com
>

^ permalink raw reply

* Re: ATH10K VLAN firmware issue
From: Bruno Antunes @ 2016-11-07 12:01 UTC (permalink / raw)
  To: Valo, Kalle
  Cc: voncken, OpenWrt Development List, linux-wireless,
	ath10k@lists.infradead.org
In-Reply-To: <87twbnueqv.fsf@kamboji.qca.qualcomm.com>

On 4 November 2016 at 21:17, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
> Bruno Antunes <baantunes@gmail.com> writes:
>
>> Old thread but I think the issue is still present.
>>
>> I'm running a setup with VLANs with WDS and ath10k cards.
>>
>> To make it work both cards must be loaded in rawmode, AP
>> and Sta, and with no security.
>>
>> I'm using a OpenWrt trunk r49941 and the most recent firmware,
>> 10.2.4.70.58, from Kalle ath10k firmware tree.
>>
>> Although it works the throughput is very bad.
>> Are there any alternatives to improve the throughput.
>
> Can someone file a bug to bugzilla about this so that all the info is
> properly stored? The more comprehensive the report is the better.
>
> https://bugzilla.kernel.org/

I will file a bug report.

But since it appears to be a firmware related issue
under what category can fill in the bug?

Thanks,
Bruno

>
> --
> Kalle Valo

^ permalink raw reply

* Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: Ben Greear @ 2016-11-07 14:06 UTC (permalink / raw)
  To: Bruno Antunes
  Cc: yu-chieh kung, Mauro Mozzarelli, linux-wireless@vger.kernel.org,
	OpenWrt Development List, ath10k@lists.infradead.org
In-Reply-To: <CABUTiXXvqQ=yrrK3wp0fck=Mcb0LSrE7_Jw6KisYOuADvo3sdQ@mail.gmail.com>

On 11/07/2016 03:54 AM, Bruno Antunes wrote:
> On 4 November 2016 at 22:23, Ben Greear <greearb@candelatech.com> wrote:
>> The bug appears that vlan-tx-stripping is unconditionally enabled in
>> at least my firmware.  I have re-compiled w/out that flag set, and it
>> appears
>> to work for me.
>>
>> Please download this firmware, rename it firmware-2.bin, make sure you
>> remove/rename
>> any firmware-5.bin (etc) so mine will load, and see if that fixes your
>> problem.
>
> Thanks for the fast reply but it only solves "half"  the problem.
>
> Now the connection between the AP and the Sta can be secure and the
> driver doesn't need to be loaded in rawmode.
>
> Unfortunatly the the throughput is still bad.
>
> iperf3 -c 10.10.4.15
> Connecting to host 10.10.4.15, port 5201
> [  4] local 10.10.4.16 port 44893 connected to 10.10.4.15 port 5201
> [ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
> [  4]   0.00-1.01   sec  42.4 KBytes   345 Kbits/sec    6   1.41 KBytes
> [  4]   1.01-2.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
> [  4]   2.01-3.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
> [  4]   3.01-4.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
> [  4]   4.01-5.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
> [  4]   5.01-6.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
> [  4]   6.01-7.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
> [  4]   7.01-8.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
> [  4]   8.01-9.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
> [  4]   9.01-10.01  sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
> - - - - - - - - - - - - - - - - - - - - - - - - -
> [ ID] Interval           Transfer     Bandwidth       Retr
> [  4]   0.00-10.01  sec  42.4 KBytes  34.7 Kbits/sec    9             sender
> [  4]   0.00-10.01  sec  0.00 Bytes  0.00 bits/sec                  receiver

You have a complex setup, so I think it would be best if you could break it into
simpler parts to test.

First, try just STA to AP, no vlans, and see if you get useful throughput.

Then try with VLANs

Then, try with WDS.

Then try with WDS and vlans.

In STA to AP mode with VLANs, it performed well for me.

Thanks,
Ben


>
> iperf Done.
>
>>
>> Please note that it is very likely you will have to use same MAC address
>> for the VLAN devices that the underlying station uses in order for this to
>> work.
>
> Can you please elaborate more?
> My setup  is the folowing.
> The connection between the AP and Sta is in WDS
> For the moment all devices are in the same VLAN.
>
> client1 --- SW1 ---- AP ...... Sta ---- SW2 --- client2
>
>
> Thanks,
> Bruno
>
>>
>> https://www.candelatech.com/downloads/tmp/firmware-2-full-community.bin
>>
>>
>> Thanks,
>> Ben
>>
>>
>>
>
>> Ben Greear <greearb@candelatech.com>
>> Candela Technologies Inc  http://www.candelatech.com
>>
>

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* Re: [PATCH 1/2] cfg80211: Add support to set tx power for a station associated
From: Ashok Raj Nagarajan @ 2016-11-07 14:10 UTC (permalink / raw)
  To: Ben Greear; +Cc: Johannes Berg, Ashok Raj Nagarajan, linux-wireless, ath10k
In-Reply-To: <579F4E4E.80103@candelatech.com>

On 2016-08-01 18:57, Ben Greear wrote:
> On 08/01/2016 02:29 AM, Johannes Berg wrote:
>> 
>>> Sure.. First use case will be to help with the problem of legacy
>>> client devices that roam across multiple APs. It is a classic
>>> enterprise Wi-Fi AP problem,  often managed by a "network controller"
>>> unit that is connected to all the APs.
>>> The problem is how to handle seamless handoff of clients between
>>> multiple  APs while maximizing the client throughput and minimizing
>>> disruption of IP application services like VoIP calls and video
>>> streaming. A legacy client will often  hold onto an AP association,
>>> even down to 1 Mbps as it roams away. Instead,  if the AP can
>>> recognise that the client RSSI (and therefore throughput) is poor, it
>>> can "drop" the Tx power significantly (just to that client) such that
>>> it forcesthe client to look for a better, closer, and therefore
>>> higher-throughputassociation. It would "give it a kick" without
>>> blacklisting it. It just needsto hold the power low for the small
>>> amount of time it takes to convince it to go away.
>> 
>> Not sure that *works* since implementations may just compare beacon
>> signal strength and hold on to the AP based on that, but it does seem
>> like a reasonable use case.
> 
> How is that better than just kicking the station deliberately and/or
> refusing to send frames to it at all?
> 

Ben, deliberately kicking out the station can potentially cause the 
black
listing behaviour on the client side and results in connection failures. 
Each
client handles the kickout logic differently. Reducing the tx power, 
causes the
station to trigger its roaming algorithm.

>> 
>> How would this interact with automatic adjustment though?
>> 

Johannes,

In the case of manual intervention by user, the firmware will check 
three
values - regulatory domain, automatic tx power and user entered value. 
System
will always cap to the minimum of these values and see to that we do not 
exceed
the regulatory power limits.

If there are no more comments I will resent this patch series after 
rebase.

Thanks,
Ashok

>> johannes
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe 
>> linux-wireless" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> 

^ permalink raw reply

* Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: Bruno Antunes @ 2016-11-07 14:13 UTC (permalink / raw)
  To: Ben Greear
  Cc: yu-chieh kung, Mauro Mozzarelli, linux-wireless@vger.kernel.org,
	OpenWrt Development List, ath10k@lists.infradead.org
In-Reply-To: <58208A6A.5040307@candelatech.com>

On 7 November 2016 at 14:06, Ben Greear <greearb@candelatech.com> wrote:
> On 11/07/2016 03:54 AM, Bruno Antunes wrote:
>>
>> On 4 November 2016 at 22:23, Ben Greear <greearb@candelatech.com> wrote:
>>>
>>> The bug appears that vlan-tx-stripping is unconditionally enabled in
>>> at least my firmware.  I have re-compiled w/out that flag set, and it
>>> appears
>>> to work for me.
>>>
>>> Please download this firmware, rename it firmware-2.bin, make sure you
>>> remove/rename
>>> any firmware-5.bin (etc) so mine will load, and see if that fixes your
>>> problem.
>>
>>
>> Thanks for the fast reply but it only solves "half"  the problem.
>>
>> Now the connection between the AP and the Sta can be secure and the
>> driver doesn't need to be loaded in rawmode.
>>
>> Unfortunatly the the throughput is still bad.
>>
>> iperf3 -c 10.10.4.15
>> Connecting to host 10.10.4.15, port 5201
>> [  4] local 10.10.4.16 port 44893 connected to 10.10.4.15 port 5201
>> [ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
>> [  4]   0.00-1.01   sec  42.4 KBytes   345 Kbits/sec    6   1.41 KBytes
>> [  4]   1.01-2.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
>> [  4]   2.01-3.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
>> [  4]   3.01-4.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
>> [  4]   4.01-5.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
>> [  4]   5.01-6.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
>> [  4]   6.01-7.01   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
>> [  4]   7.01-8.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
>> [  4]   8.01-9.01   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
>> [  4]   9.01-10.01  sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
>> - - - - - - - - - - - - - - - - - - - - - - - - -
>> [ ID] Interval           Transfer     Bandwidth       Retr
>> [  4]   0.00-10.01  sec  42.4 KBytes  34.7 Kbits/sec    9
>> sender
>> [  4]   0.00-10.01  sec  0.00 Bytes  0.00 bits/sec
>> receiver
>
>
> You have a complex setup, so I think it would be best if you could break it
> into
> simpler parts to test.

Some of the parts I already tested and are working
>
> First, try just STA to AP, no vlans, and see if you get useful throughput.
>
Works fine

> Then try with VLANs
>
To Do

> Then, try with WDS.

Works fine
>
> Then try with WDS and vlans.
>
The ultimate goal...

> In STA to AP mode with VLANs, it performed well for me.
>
> Thanks,
> Ben
>
>
>>
>> iperf Done.
>>
>>>
>>> Please note that it is very likely you will have to use same MAC address
>>> for the VLAN devices that the underlying station uses in order for this
>>> to
>>> work.
>>
>>
>> Can you please elaborate more?
>> My setup  is the folowing.
>> The connection between the AP and Sta is in WDS
>> For the moment all devices are in the same VLAN.
>>
>> client1 --- SW1 ---- AP ...... Sta ---- SW2 --- client2
>>
>>
>> Thanks,
>> Bruno
>>
>>>
>>> https://www.candelatech.com/downloads/tmp/firmware-2-full-community.bin
>>>
>>>
>>> Thanks,
>>> Ben
>>>
>>>
>>>
>>
>>> Ben Greear <greearb@candelatech.com>
>>> Candela Technologies Inc  http://www.candelatech.com
>>>
>>
>
> --
> Ben Greear <greearb@candelatech.com>
> Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* Re: [PATCH 1/2] cfg80211: Add support to set tx power for a station associated
From: Ben Greear @ 2016-11-07 14:18 UTC (permalink / raw)
  To: Ashok Raj Nagarajan
  Cc: Johannes Berg, Ashok Raj Nagarajan, linux-wireless, ath10k
In-Reply-To: <8908f6e7bb8ca043fbeb07ee8b004e8f@codeaurora.org>



On 11/07/2016 06:10 AM, Ashok Raj Nagarajan wrote:
> On 2016-08-01 18:57, Ben Greear wrote:
>> On 08/01/2016 02:29 AM, Johannes Berg wrote:
>>>
>>>> Sure.. First use case will be to help with the problem of legacy
>>>> client devices that roam across multiple APs. It is a classic
>>>> enterprise Wi-Fi AP problem,  often managed by a "network controller"
>>>> unit that is connected to all the APs.
>>>> The problem is how to handle seamless handoff of clients between
>>>> multiple  APs while maximizing the client throughput and minimizing
>>>> disruption of IP application services like VoIP calls and video
>>>> streaming. A legacy client will often  hold onto an AP association,
>>>> even down to 1 Mbps as it roams away. Instead,  if the AP can
>>>> recognise that the client RSSI (and therefore throughput) is poor, it
>>>> can "drop" the Tx power significantly (just to that client) such that
>>>> it forcesthe client to look for a better, closer, and therefore
>>>> higher-throughputassociation. It would "give it a kick" without
>>>> blacklisting it. It just needsto hold the power low for the small
>>>> amount of time it takes to convince it to go away.
>>>
>>> Not sure that *works* since implementations may just compare beacon
>>> signal strength and hold on to the AP based on that, but it does seem
>>> like a reasonable use case.
>>
>> How is that better than just kicking the station deliberately and/or
>> refusing to send frames to it at all?
>>
>
> Ben, deliberately kicking out the station can potentially cause the black
> listing behaviour on the client side and results in connection failures. Each
> client handles the kickout logic differently. Reducing the tx power, causes the
> station to trigger its roaming algorithm.

We tested some phones a year or so ago, and used a variable attenuator
to decrease the signal of one AP while ramping up signal of a second AP.
They did not roam until they lost connection, and since we were not using an isolation
chamber, we could not get the AP signal less than around -75 DB, so in our test,
the phones often did not roam at all.

http://www.candelatech.com/cookbook.php?vol=wifire&book=Emulating+Station+Motion+with+Programmable+Attenuator

So, I am not sure you can assume much about scanning behaviour either.  Maybe newer
phones are better...

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* [PATCH 0/8] iw: Add common chandef parser and new DFS related commands
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg

From: Benjamin Berg <benjamin.berg@open-mesh.com>

Hi,

This patchset adds commands for doing a CAC and sending CSA.

Another change is that parsing of command line frequency and channel
definitions is split out so that it can be shared between the different
users.

Benjamin

Benjamin Berg (7):
  util: Add generic frequency/channel command line handler
  phy: Use common freqchan helper for setting the operating channel
  ibss: Use common freqchan helper for joining an ibss
  mesh: Use common freqchan helper for joining a mesh
  Add cac command to allow clearing channels
  Add commands to send CSA
  Print frequency of radar events.

Simon Wunderlich (1):
  Add flag for DFS handling in IBSS

 event.c     |  48 +++++------
 ibss.c      |  78 ++++--------------
 interface.c |  72 ++++++++++++++++
 iw.h        |  11 +++
 mesh.c      |  67 +++------------
 phy.c       | 266 ++++++++++++++++++++++++++++++++++++------------------------
 util.c      | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 533 insertions(+), 248 deletions(-)

-- 
2.10.2

^ permalink raw reply

* [PATCH 2/8] phy: Use common freqchan helper for setting the operating channel
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

From: Benjamin Berg <benjamin.berg@open-mesh.com>

Simplify code by using the helper which has been introduced earlier.

Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 phy.c | 143 ++++++++++++------------------------------------------------------
 1 file changed, 25 insertions(+), 118 deletions(-)

diff --git a/phy.c b/phy.c
index c57a71f..266de4d 100644
--- a/phy.c
+++ b/phy.c
@@ -183,140 +183,47 @@ static int handle_name(struct nl80211_state *state,
 COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
 	"Rename this wireless device.");
 
-static int handle_freqs(struct nl_msg *msg, int argc, char **argv)
-{
-	static const struct {
-		const char *name;
-		unsigned int val;
-	} bwmap[] = {
-		{ .name = "20", .val = NL80211_CHAN_WIDTH_20, },
-		{ .name = "40", .val = NL80211_CHAN_WIDTH_40, },
-		{ .name = "80", .val = NL80211_CHAN_WIDTH_80, },
-		{ .name = "80+80", .val = NL80211_CHAN_WIDTH_80P80, },
-		{ .name = "160", .val = NL80211_CHAN_WIDTH_160, },
-	};
-	uint32_t freq;
-	unsigned int i, bwval = NL80211_CHAN_WIDTH_20_NOHT;
-	char *end;
-
-	if (argc < 1)
-		return 1;
-
-	for (i = 0; i < ARRAY_SIZE(bwmap); i++) {
-		if (strcasecmp(bwmap[i].name, argv[0]) == 0) {
-			bwval = bwmap[i].val;
-			break;
-		}
-	}
-
-	if (bwval == NL80211_CHAN_WIDTH_20_NOHT)
-		return 1;
-
-	NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, bwval);
-
-	if (argc == 1)
-		return 0;
-
-	/* center freq 1 */
-	if (!*argv[1])
-		return 1;
-	freq = strtoul(argv[1], &end, 10);
-	if (*end)
-		return 1;
-	NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq);
-
-	if (argc == 2)
-		return 0;
-
-	/* center freq 2 */
-	if (!*argv[2])
-		return 1;
-	freq = strtoul(argv[2], &end, 10);
-	if (*end)
-		return 1;
-	NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2, freq);
-
-	return 0;
- nla_put_failure:
-	return -ENOBUFS;
-}
-
-static int handle_freqchan(struct nl_msg *msg, bool chan,
-			   int argc, char **argv)
-{
-	char *end;
-	static const struct {
-		const char *name;
-		unsigned int val;
-	} htmap[] = {
-		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
-		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
-		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
-	};
-	unsigned int htval = NL80211_CHAN_NO_HT;
-	unsigned int freq;
-	unsigned int i;
-
-	if (!argc || argc > 4)
-		return 1;
-
-	if (!*argv[0])
-		return 1;
-	freq = strtoul(argv[0], &end, 10);
-	if (*end)
-		return 1;
-
-	if (chan) {
-		enum nl80211_band band;
-		band = freq <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
-		freq = ieee80211_channel_to_frequency(freq, band);
-	}
-
-	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
-
-	if (argc > 2) {
-		return handle_freqs(msg, argc - 1, argv + 1);
-	} else if (argc == 2) {
-		for (i = 0; i < ARRAY_SIZE(htmap); i++) {
-			if (strcasecmp(htmap[i].name, argv[1]) == 0) {
-				htval = htmap[i].val;
-				break;
-			}
-		}
-		if (htval == NL80211_CHAN_NO_HT)
-			return handle_freqs(msg, argc - 1, argv + 1);
-	}
-
-	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
-
-	return 0;
- nla_put_failure:
-	return -ENOBUFS;
-}
-
 static int handle_freq(struct nl80211_state *state, struct nl_msg *msg,
 		       int argc, char **argv,
 		       enum id_input id)
 {
-	return handle_freqchan(msg, false, argc, argv);
+	struct chandef chandef;
+	int res;
+
+	res = parse_freqchan(&chandef, false, argc, argv, NULL);
+	if (res)
+		return res;
+
+	return put_chandef(msg, &chandef);
 }
-COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
+
+COMMAND(set, freq,
+	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
 	"Set frequency/channel the hardware is using, including HT\n"
 	"configuration.");
-COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]\n"
-		   "<control freq> [20|40|80|80+80|160] [<center freq 1>] [<center freq 2>]",
+COMMAND(set, freq,
+	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
 
 static int handle_chan(struct nl80211_state *state, struct nl_msg *msg,
 		       int argc, char **argv,
 		       enum id_input id)
 {
-	return handle_freqchan(msg, true, argc, argv);
+	struct chandef chandef;
+	int res;
+
+	res = parse_freqchan(&chandef, true, argc, argv, NULL);
+	if (res)
+		return res;
+
+	return put_chandef(msg, &chandef);
 }
-COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
+COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
-COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
+COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
 
 static int handle_fragmentation(struct nl80211_state *state,
-- 
2.10.2

^ permalink raw reply related

* [PATCH 1/8] util: Add generic frequency/channel command line handler
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

From: Benjamin Berg <benjamin.berg@open-mesh.com>

The ability to parse channel definitions is required in a lot of places
inside iw. However, right now each of these duplicates a lot of code to
handle it.

So add a new helper which can be used everywhere.

Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 iw.h   |  10 +++
 util.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 249 insertions(+)

diff --git a/iw.h b/iw.h
index 2837bd3..7d56391 100644
--- a/iw.h
+++ b/iw.h
@@ -70,6 +70,14 @@ struct chanmode {
 	int chantype; /* for older kernel */
 };
 
+struct chandef {
+	enum nl80211_chan_width width;
+
+	unsigned int control_freq;
+	unsigned int center_freq1;
+	unsigned int center_freq2;
+};
+
 #define ARRAY_SIZE(ar) (sizeof(ar)/sizeof(ar[0]))
 #define DIV_ROUND_UP(x, y) (((x) + (y - 1)) / (y))
 
@@ -150,6 +158,8 @@ int parse_hex_mask(char *hexmask, unsigned char **result, size_t *result_len,
 unsigned char *parse_hex(char *hex, size_t *outlen);
 
 int parse_keys(struct nl_msg *msg, char **argv, int argc);
+int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv, int *parsed);
+int put_chandef(struct nl_msg *msg, struct chandef *chandef);
 
 void print_ht_mcs(const __u8 *mcs);
 void print_ampdu_length(__u8 exponent);
diff --git a/util.c b/util.c
index a338464..833b1ce 100644
--- a/util.c
+++ b/util.c
@@ -469,6 +469,245 @@ int parse_keys(struct nl_msg *msg, char **argv, int argc)
 	return 2;
 }
 
+static int parse_freqs(struct chandef *chandef, int argc, char **argv,
+		       int *parsed)
+{
+	static const struct {
+		const char *name;
+		unsigned int val;
+	} bwmap[] = {
+		{ .name = "5", .val = NL80211_CHAN_WIDTH_5, },
+		{ .name = "10", .val = NL80211_CHAN_WIDTH_10, },
+		{ .name = "20", .val = NL80211_CHAN_WIDTH_20, },
+		{ .name = "40", .val = NL80211_CHAN_WIDTH_40, },
+		{ .name = "80", .val = NL80211_CHAN_WIDTH_80, },
+		{ .name = "80+80", .val = NL80211_CHAN_WIDTH_80P80, },
+		{ .name = "160", .val = NL80211_CHAN_WIDTH_160, },
+	};
+	uint32_t freq;
+	unsigned int i, bwval = NL80211_CHAN_WIDTH_20_NOHT;
+	char *end;
+
+	if (argc < 1)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(bwmap); i++) {
+		if (strcasecmp(bwmap[i].name, argv[0]) == 0) {
+			bwval = bwmap[i].val;
+			*parsed += 1;
+			break;
+		}
+	}
+	chandef->width = bwval;
+
+	/* First argument was not understood, give up gracefully. */
+	if (bwval == NL80211_CHAN_WIDTH_20_NOHT)
+		return 0;
+
+	if (argc < 2)
+		return 0;
+
+	/* center freq 1 */
+	if (!*argv[1])
+		return 0;
+	freq = strtoul(argv[1], &end, 10);
+	if (*end)
+		return 0;
+	*parsed += 1;
+
+	chandef->center_freq1 = freq;
+
+	if (argc < 3)
+		return 0;
+
+	/* center freq 2 */
+	if (!*argv[2])
+		return 0;
+	freq = strtoul(argv[2], &end, 10);
+	if (*end)
+		return 0;
+	chandef->center_freq2 = freq;
+
+	*parsed += 1;
+
+	return 0;
+}
+
+
+/**
+ * parse_freqchan - Parse frequency or channel definition
+ *
+ * @chandef: chandef structure to be filled in
+ * @chan: Boolean whether to parse a channel or frequency based specifier
+ * @argc: Number of arguments
+ * @argv: Array of string arguments
+ * @parsed: Pointer to return the number of used arguments, or NULL to error
+ *          out if any argument is left unused.
+ *
+ * The given chandef structure will be filled in from the command line
+ * arguments. argc/argv will be updated so that further arguments from the
+ * command line can be parsed.
+ *
+ * Note that no integer argument may follow a frequency definition to allow the
+ * user to skip the center frequency definition(s).
+ *
+ * The working specifier if chan is set are:
+ *   <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]
+ *
+ * And if frequency is set:
+ *   <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]
+ *   <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]
+ *
+ * If the mode/channel width is not given the NOHT is assumed.
+ *
+ * Return: Number of used arguments, zero or negative error number otherwise
+ */
+int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
+		   int *parsed)
+{
+	char *end;
+	static const struct chanmode chanmode[] = {
+		{ .name = "HT20",
+		  .width = NL80211_CHAN_WIDTH_20,
+		  .freq1_diff = 0,
+		  .chantype = NL80211_CHAN_HT20 },
+		{ .name = "HT40+",
+		  .width = NL80211_CHAN_WIDTH_40,
+		  .freq1_diff = 10,
+		  .chantype = NL80211_CHAN_HT40PLUS },
+		{ .name = "HT40-",
+		  .width = NL80211_CHAN_WIDTH_40,
+		  .freq1_diff = -10,
+		  .chantype = NL80211_CHAN_HT40MINUS },
+		{ .name = "NOHT",
+		  .width = NL80211_CHAN_WIDTH_20_NOHT,
+		  .freq1_diff = 0,
+		  .chantype = NL80211_CHAN_NO_HT },
+		{ .name = "5MHz",
+		  .width = NL80211_CHAN_WIDTH_5,
+		  .freq1_diff = 0,
+		  .chantype = -1 },
+		{ .name = "10MHz",
+		  .width = NL80211_CHAN_WIDTH_10,
+		  .freq1_diff = 0,
+		  .chantype = -1 },
+		{ .name = "80MHz",
+		  .width = NL80211_CHAN_WIDTH_80,
+		  .freq1_diff = 0,
+		  .chantype = -1 },
+	};
+	const struct chanmode *chanmode_selected = NULL;
+	unsigned int freq;
+	unsigned int i;
+	int _parsed = 0;
+	int res = 0;
+
+	if (argc < 1)
+		return 1;
+
+	if (!argv[0])
+		goto out;
+	freq = strtoul(argv[0], &end, 10);
+	if (*end) {
+		res = 1;
+		goto out;
+	}
+
+	_parsed += 1;
+
+	memset(chandef, 0, sizeof(struct chandef));
+
+	if (chan) {
+		enum nl80211_band band;
+
+		band = freq <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+		freq = ieee80211_channel_to_frequency(freq, band);
+	}
+	chandef->control_freq = freq;
+	/* Assume 20MHz NOHT channel for now. */
+	chandef->center_freq1 = freq;
+
+	/* Try to parse HT mode definitions */
+	if (argc > 1) {
+		for (i = 0; i < ARRAY_SIZE(chanmode); i++) {
+			if (strcasecmp(chanmode[i].name, argv[1]) == 0) {
+				chanmode_selected = &chanmode[i];
+				_parsed += 1;
+				break;
+			}
+		}
+	}
+
+	/* channel mode given, use it and return. */
+	if (chanmode_selected) {
+		chandef->center_freq1 = get_cf1(chanmode_selected, freq);
+		chandef->width = chanmode_selected->width;
+		goto out;
+	}
+
+	/* This was a only a channel definition, nothing further may follow. */
+	if (chan)
+		goto out;
+
+	res = parse_freqs(chandef, argc - 1, argv + 1, &_parsed);
+
+ out:
+	/* Error out if parsed is NULL. */
+	if (!parsed && _parsed != argc)
+		return 1;
+
+	if (parsed)
+		*parsed = _parsed;
+
+	return res;
+}
+
+int put_chandef(struct nl_msg *msg, struct chandef *chandef)
+{
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chandef->control_freq);
+	NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width);
+
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_20_NOHT:
+		NLA_PUT_U32(msg,
+			    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+			    NL80211_CHAN_NO_HT);
+		break;
+	case NL80211_CHAN_WIDTH_20:
+		NLA_PUT_U32(msg,
+			    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+			    NL80211_CHAN_HT20);
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		if (chandef->control_freq > chandef->center_freq1)
+			NLA_PUT_U32(msg,
+				    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+				    NL80211_CHAN_HT40MINUS);
+		else
+			NLA_PUT_U32(msg,
+				    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+				    NL80211_CHAN_HT40PLUS);
+		break;
+	default:
+		break;
+	}
+
+	if (chandef->center_freq1)
+		NLA_PUT_U32(msg,
+			    NL80211_ATTR_CENTER_FREQ1,
+			    chandef->center_freq1);
+
+	if (chandef->center_freq2)
+		NLA_PUT_U32(msg,
+			    NL80211_ATTR_CENTER_FREQ2,
+			    chandef->center_freq2);
+
+	return 0;
+
+ nla_put_failure:
+	return -ENOBUFS;
+}
+
 static void print_mcs_index(const __u8 *mcs)
 {
 	int mcs_bit, prev_bit = -2, prev_cont = 0;
-- 
2.10.2

^ permalink raw reply related

* [PATCH 3/8] ibss: Use common freqchan helper for joining an ibss
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

Simplify code by using the helper which has been introduced earlier.

Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 ibss.c | 72 ++++++++++--------------------------------------------------------
 1 file changed, 10 insertions(+), 62 deletions(-)

diff --git a/ibss.c b/ibss.c
index 2b0b495..84f1e95 100644
--- a/ibss.c
+++ b/ibss.c
@@ -13,45 +13,14 @@ static int join_ibss(struct nl80211_state *state,
 		     enum id_input id)
 {
 	char *end;
+	struct chandef chandef;
 	unsigned char abssid[6];
 	unsigned char rates[NL80211_MAX_SUPP_RATES];
 	int n_rates = 0;
 	char *value = NULL, *sptr = NULL;
 	float rate;
 	int bintval;
-	unsigned int i;
-	unsigned long freq;
-	const struct chanmode *chanmode_selected = NULL;
-	static const struct chanmode chanmode[] = {
-		{ .name = "HT20",
-		  .width = NL80211_CHAN_WIDTH_20,
-		  .freq1_diff = 0,
-		  .chantype = NL80211_CHAN_HT20 },
-		{ .name = "HT40+",
-		  .width = NL80211_CHAN_WIDTH_40,
-		  .freq1_diff = 10,
-		  .chantype = NL80211_CHAN_HT40PLUS },
-		{ .name = "HT40-",
-		  .width = NL80211_CHAN_WIDTH_40,
-		  .freq1_diff = -10,
-		  .chantype = NL80211_CHAN_HT40MINUS },
-		{ .name = "NOHT",
-		  .width = NL80211_CHAN_WIDTH_20_NOHT,
-		  .freq1_diff = 0,
-		  .chantype = NL80211_CHAN_NO_HT },
-		{ .name = "5MHz",
-		  .width = NL80211_CHAN_WIDTH_5,
-		  .freq1_diff = 0,
-		  .chantype = -1 },
-		{ .name = "10MHz",
-		  .width = NL80211_CHAN_WIDTH_10,
-		  .freq1_diff = 0,
-		  .chantype = -1 },
-		{ .name = "80MHz",
-		  .width = NL80211_CHAN_WIDTH_80,
-		  .freq1_diff = 0,
-		  .chantype = -1 },
-	};
+	int parsed, err;
 
 	if (argc < 2)
 		return 1;
@@ -61,37 +30,16 @@ static int join_ibss(struct nl80211_state *state,
 	argv++;
 	argc--;
 
-	/* freq */
-	freq = strtoul(argv[0], &end, 10);
-	if (*end != '\0')
-		return 1;
-
-	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
-	argv++;
-	argc--;
+	err = parse_freqchan(&chandef, false, argc, argv, &parsed);
+	if (err)
+		return err;
 
-	if (argc) {
-		for (i = 0; i < ARRAY_SIZE(chanmode); i++) {
-			if (strcasecmp(chanmode[i].name, argv[0]) == 0) {
-				chanmode_selected = &chanmode[i];
-				break;
-			}
-		}
-		if (chanmode_selected) {
-			NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-				    chanmode_selected->width);
-			NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1,
-				    get_cf1(chanmode_selected, freq));
-			if (chanmode_selected->chantype != -1)
-				NLA_PUT_U32(msg,
-					    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
-					    chanmode_selected->chantype);
+	argv += parsed;
+	argc -= parsed;
 
-			argv++;
-			argc--;
-		}
-
-	}
+	put_chandef(msg, &chandef);
+	if (err)
+		return err;
 
 	if (argc && strcmp(argv[0], "fixed-freq") == 0) {
 		NLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);
-- 
2.10.2

^ permalink raw reply related

* [PATCH 5/8] Add cac command to allow clearing channels
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

From: Benjamin Berg <benjamin.berg@open-mesh.com>

Allow the user to start a CAC for clearing DFS channels.

Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 phy.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/phy.c b/phy.c
index 266de4d..be31820 100644
--- a/phy.c
+++ b/phy.c
@@ -226,6 +226,151 @@ COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
 COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
 
+
+struct cac_event {
+	int ret;
+	uint32_t freq;
+};
+
+static int print_cac_event(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	enum nl80211_radar_event event_type;
+	struct cac_event *cac_event = arg;
+	uint32_t freq;
+
+	if (gnlh->cmd != NL80211_CMD_RADAR_DETECT)
+		return NL_SKIP;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (!tb[NL80211_ATTR_RADAR_EVENT] || !tb[NL80211_ATTR_WIPHY_FREQ])
+		return NL_SKIP;
+
+	freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
+	event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
+	if (freq != cac_event->freq)
+		return NL_SKIP;
+
+	switch (event_type) {
+	case NL80211_RADAR_DETECTED:
+		printf("%d MHz: radar detected\n", freq);
+		break;
+	case NL80211_RADAR_CAC_FINISHED:
+		printf("%d MHz: CAC finished\n", freq);
+		break;
+	case NL80211_RADAR_CAC_ABORTED:
+		printf("%d MHz: CAC was aborted\n", freq);
+		break;
+	case NL80211_RADAR_NOP_FINISHED:
+		printf("%d MHz: NOP finished\n", freq);
+		break;
+	default:
+		printf("%d MHz: unknown radar event\n", freq);
+	}
+	cac_event->ret = 0;
+
+	return NL_SKIP;
+}
+
+static int handle_cac_trigger(struct nl80211_state *state,
+			    struct nl_msg *msg,
+			    int argc, char **argv,
+			    enum id_input id)
+{
+	struct chandef chandef;
+	int res;
+
+	if (argc < 2)
+		return 1;
+
+	if (strcmp(argv[0], "channel") == 0) {
+		res = parse_freqchan(&chandef, true, argc - 1, argv + 1, NULL);
+	} else if (strcmp(argv[0], "freq") == 0) {
+		res = parse_freqchan(&chandef, false, argc - 1, argv + 1, NULL);
+	} else {
+		return 1;
+	}
+
+	if (res)
+		return res;
+
+	return put_chandef(msg, &chandef);
+}
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+	return NL_OK;
+}
+
+static int handle_cac(struct nl80211_state *state,
+		      struct nl_msg *msg,
+		      int argc, char **argv,
+		      enum id_input id)
+{
+	int err;
+	struct nl_cb *radar_cb;
+	struct chandef chandef;
+	struct cac_event cac_event;
+	char **cac_trigger_argv = NULL;
+
+	radar_cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
+	if (!radar_cb)
+		return 1;
+
+	if (argc < 3)
+		return 1;
+
+	if (strcmp(argv[2], "channel") == 0) {
+		err = parse_freqchan(&chandef, true, argc - 3, argv + 3, NULL);
+	} else if (strcmp(argv[2], "freq") == 0) {
+		err = parse_freqchan(&chandef, false, argc - 3, argv + 3, NULL);
+	} else {
+		return 1;
+	}
+
+	cac_trigger_argv = calloc(argc + 1, sizeof(char*));
+	if (!cac_trigger_argv)
+		return -ENOMEM;
+
+	cac_trigger_argv[0] = argv[0];
+	cac_trigger_argv[1] = "cac";
+	cac_trigger_argv[2] = "trigger";
+	memcpy(&cac_trigger_argv[3], &argv[2], (argc - 2) * sizeof(char*));
+
+	err = handle_cmd(state, id, argc + 1, cac_trigger_argv);
+	free(cac_trigger_argv);
+	if (err)
+		return err;
+
+	cac_event.ret = 1;
+	cac_event.freq = chandef.control_freq;
+
+	__prepare_listen_events(state);
+	nl_socket_set_cb(state->nl_sock, radar_cb);
+
+	/* need to turn off sequence number checking */
+	nl_cb_set(radar_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+	nl_cb_set(radar_cb, NL_CB_VALID, NL_CB_CUSTOM, print_cac_event, &cac_event);
+	while (cac_event.ret > 0)
+		nl_recvmsgs(state->nl_sock, radar_cb);
+
+	return 0;
+}
+TOPLEVEL(cac, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	      "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	      "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
+	 0, 0, CIB_NETDEV, handle_cac, NULL);
+COMMAND(cac, trigger,
+	"channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
+	NL80211_CMD_RADAR_DETECT, 0, CIB_NETDEV, handle_cac_trigger,
+	"Start or trigger a channel availability check (CAC) looking to look for\n"
+	"radars on the given channel.");
+
 static int handle_fragmentation(struct nl80211_state *state,
 				struct nl_msg *msg,
 				int argc, char **argv,
-- 
2.10.2

^ permalink raw reply related

* [PATCH 7/8] Add flag for DFS handling in IBSS
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

From: Simon Wunderlich <sw@simonwunderlich.de>

When Userspace is capable of handling DFS, it can inform the kernel
about that by sending the NL80211_ATTR_HANDLE_DFS attribute when joining
an IBSS. DFS channels will then be unlocked.

Note that this flag is only added for debugging purposes and therefore
hidden from the user by prefixing with __ and not documenting it.

Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 ibss.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/ibss.c b/ibss.c
index 84f1e95..7087cc9 100644
--- a/ibss.c
+++ b/ibss.c
@@ -47,6 +47,12 @@ static int join_ibss(struct nl80211_state *state,
 		argc--;
 	}
 
+	if (argc && strcmp(argv[0], "__dfs-enable") == 0) {
+		NLA_PUT_FLAG(msg, NL80211_ATTR_HANDLE_DFS);
+		argv++;
+		argc--;
+	}
+
 	if (argc) {
 		if (mac_addr_a2n(abssid, argv[0]) == 0) {
 			NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
-- 
2.10.2

^ permalink raw reply related

* [PATCH 6/8] Add commands to send CSA
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

From: Benjamin Berg <benjamin.berg@open-mesh.com>

Add a new set of commands to send a CSA. Both the number of beacons and the
flag to block TX can be given optionally.

Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 interface.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 iw.h        |  1 +
 2 files changed, 73 insertions(+)

diff --git a/interface.c b/interface.c
index 57dd3c3..1c9ebfb 100644
--- a/interface.c
+++ b/interface.c
@@ -644,3 +644,75 @@ nla_put_failure:
 COMMAND(set, mcast_rate, "<rate in Mbps>",
 	NL80211_CMD_SET_MCAST_RATE, 0, CIB_NETDEV, set_mcast_rate,
 	"Set the multicast bitrate.");
+
+
+static int handle_chanfreq(struct nl80211_state *state, struct nl_msg *msg,
+			   bool chan, int argc, char **argv,
+			   enum id_input id)
+{
+	struct chandef chandef;
+	int res;
+	int parsed;
+	char *end;
+
+	res = parse_freqchan(&chandef, chan, argc, argv, &parsed);
+	if (res)
+		return res;
+
+	argc -= parsed;
+	argv += parsed;
+
+	while (argc) {
+		unsigned int beacons = 10;
+
+		if (strcmp(argv[0], "beacons") == 0) {
+			if (argc < 2)
+				return 1;
+
+			beacons = strtol(argv[1], &end, 10);
+			if (*end)
+				return 1;
+
+			argc -= 2;
+			argv += 2;
+
+			NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, beacons);
+		} else if (strcmp(argv[0], "block-tx") == 0) {
+			argc -= 1;
+			argv += 1;
+
+			NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX);
+		} else {
+			return 1;
+		}
+	}
+
+	return put_chandef(msg, &chandef);
+
+ nla_put_failure:
+	return -ENOBUFS;
+}
+
+static int handle_freq(struct nl80211_state *state, struct nl_msg *msg,
+		       int argc, char **argv,
+		       enum id_input id)
+{
+	return handle_chanfreq(state, msg, false, argc, argv, id);
+}
+
+static int handle_chan(struct nl80211_state *state, struct nl_msg *msg,
+		       int argc, char **argv,
+		       enum id_input id)
+{
+	return handle_chanfreq(state, msg, true, argc, argv, id);
+}
+
+SECTION(switch);
+COMMAND(switch, freq,
+	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons <count>] [block-tx]\n"
+	"<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]] [beacons <count>] [block-tx]",
+	NL80211_CMD_CHANNEL_SWITCH, 0, CIB_NETDEV, handle_freq,
+	"Switch the operating channel by sending a channel switch announcement (CSA).");
+COMMAND(switch, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons <count>] [block-tx]",
+	NL80211_CMD_CHANNEL_SWITCH, 0, CIB_NETDEV, handle_chan, NULL);
+
diff --git a/iw.h b/iw.h
index 7d56391..0857baf 100644
--- a/iw.h
+++ b/iw.h
@@ -202,6 +202,7 @@ int get_cf1(const struct chanmode *chanmode, unsigned long freq);
 	"[randomise[=<addr>/<mask>]]"
 int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv);
 
+DECLARE_SECTION(switch);
 DECLARE_SECTION(set);
 DECLARE_SECTION(get);
 
-- 
2.10.2

^ permalink raw reply related

* [PATCH 4/8] mesh: Use common freqchan helper for joining a mesh
From: Benjamin Berg @ 2016-11-07 14:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, sw, Benjamin Berg, Benjamin Berg
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

Simplify code by using the helper which has been introduced earlier.

Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 mesh.c | 67 +++++++++++-------------------------------------------------------
 1 file changed, 11 insertions(+), 56 deletions(-)

diff --git a/mesh.c b/mesh.c
index a0047fe..97f236b 100644
--- a/mesh.c
+++ b/mesh.c
@@ -446,31 +446,6 @@ static int join_mesh(struct nl80211_state *state,
 	unsigned char rates[NL80211_MAX_SUPP_RATES];
 	int bintval, dtim_period, n_rates = 0;
 	char *end, *value = NULL, *sptr = NULL;
-	unsigned int i;
-	unsigned long freq = 0;
-	const struct chanmode *chanmode_selected = NULL;
-	static const struct chanmode chanmode[] = {
-		{ .name = "HT20",
-		  .width = NL80211_CHAN_WIDTH_20,
-		  .freq1_diff = 0,
-		  .chantype = NL80211_CHAN_HT20 },
-		{ .name = "HT40+",
-		  .width = NL80211_CHAN_WIDTH_40,
-		  .freq1_diff = 10,
-		  .chantype = NL80211_CHAN_HT40PLUS },
-		{ .name = "HT40-",
-		  .width = NL80211_CHAN_WIDTH_40,
-		  .freq1_diff = -10,
-		  .chantype = NL80211_CHAN_HT40MINUS },
-		{ .name = "NOHT",
-		  .width = NL80211_CHAN_WIDTH_20_NOHT,
-		  .freq1_diff = 0,
-		  .chantype = NL80211_CHAN_NO_HT },
-		{ .name = "80MHz",
-		  .width = NL80211_CHAN_WIDTH_80,
-		  .freq1_diff = 0,
-		  .chantype = -1 },
-	};
 
 	if (argc < 1)
 		return 1;
@@ -481,40 +456,20 @@ static int join_mesh(struct nl80211_state *state,
 
 	/* freq */
 	if (argc > 1 && strcmp(argv[0], "freq") == 0) {
-		argv++;
-		argc--;
-
-		freq = strtoul(argv[0], &end, 10);
-		if (*end != '\0')
-			return 1;
-		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
-
-		argv++;
-		argc--;
-	}
+		struct chandef chandef;
+		int err, parsed;
 
-	/* channel type */
-	if (argc) {
-		for (i = 0; i < ARRAY_SIZE(chanmode); i++) {
-			if (strcasecmp(chanmode[i].name, argv[0]) == 0) {
-				chanmode_selected = &chanmode[i];
-				break;
-			}
-		}
+		err = parse_freqchan(&chandef, false, argc - 1, argv + 1,
+				     &parsed);
+		if (err)
+			return err;
 
-		if (chanmode_selected) {
-			NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-				    chanmode_selected->width);
-			NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1,
-				    get_cf1(chanmode_selected, freq));
-			if (chanmode_selected->chantype != -1)
-				NLA_PUT_U32(msg,
-					    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
-					    chanmode_selected->chantype);
+		argv += parsed + 1;
+		argc -= parsed + 1;
 
-			argv++;
-			argc--;
-		}
+		put_chandef(msg, &chandef);
+		if (err)
+			return err;
 	}
 
 	/* basic rates */
-- 
2.10.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox