diff mbox

nl80211: fix channel switching with VHT80

Message ID 1390917401-7768-1-git-send-email-michal.kazior@tieto.com
State Accepted
Headers show

Commit Message

Michal Kazior Jan. 28, 2014, 1:56 p.m. UTC
It is possible for channel switch notification to
be missing channel type attribute. This is true at
least for VHT80. This led to
iface->conf->secondary_channel being set to 0.
This in turn made subsequent DFS-triggered CSA to
fail due to invalid frequency parameters.

Signed-hostap: Michal Kazior <michal.kazior@tieto.com>
---
 src/drivers/driver_nl80211.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

Comments

Jouni Malinen Jan. 30, 2014, 1:14 p.m. UTC | #1
On Tue, Jan 28, 2014 at 02:56:41PM +0100, Michal Kazior wrote:
> It is possible for channel switch notification to
> be missing channel type attribute. This is true at
> least for VHT80. This led to
> iface->conf->secondary_channel being set to 0.
> This in turn made subsequent DFS-triggered CSA to
> fail due to invalid frequency parameters.

Thanks, applied.
diff mbox

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 646d3f8..f11f2f4 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1550,6 +1550,33 @@  static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
+{
+	int freq1 = 0;
+
+	switch (convert2width(width)) {
+	case CHAN_WIDTH_20_NOHT:
+	case CHAN_WIDTH_20:
+		return 0;
+	case CHAN_WIDTH_40:
+		freq1 = cf1 - 10;
+		break;
+	case CHAN_WIDTH_80:
+		freq1 = cf1 - 30;
+		break;
+	case CHAN_WIDTH_160:
+		freq1 = cf1 - 70;
+		break;
+	case CHAN_WIDTH_UNKNOWN:
+	case CHAN_WIDTH_80P80:
+		/* FIXME: implement this */
+		return 0;
+	}
+
+	return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1;
+}
+
+
 static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr *ifindex, struct nlattr *freq,
 				 struct nlattr *type, struct nlattr *bw,
@@ -1591,6 +1618,15 @@  static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 			chan_offset = -1;
 			break;
 		}
+	} else if (bw && cf1) {
+		/* This can happen for example with VHT80 ch switch */
+		chan_offset = calculate_chan_offset(nla_get_u32(bw),
+						    nla_get_u32(freq),
+						    nla_get_u32(cf1),
+						    cf2 ? nla_get_u32(cf2) : 0);
+	} else {
+		wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information."
+			   " Future channel definition calculations will fail");
 	}
 
 	os_memset(&data, 0, sizeof(data));