]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Fix channel switching with VHT80
authorMichal Kazior <michal.kazior@tieto.com>
Tue, 28 Jan 2014 13:56:41 +0000 (14:56 +0100)
committerJouni Malinen <j@w1.fi>
Thu, 30 Jan 2014 11:58:48 +0000 (13:58 +0200)
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

index 90a73f7196d301927167ec73a66e61c85040fc1b..760170c63c56e206c69939ef65002a842db5232e 100644 (file)
@@ -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,14 @@ 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 - following channel definition calculations may fail");
        }
 
        os_memset(&data, 0, sizeof(data));