nl80211: Specify CSA offsets in send_mlme() driver op
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Tue, 8 Sep 2015 09:46:26 +0000 (12:46 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 3 Oct 2015 18:07:35 +0000 (21:07 +0300)
Some management frames contain CSA counters which should be updated by
kernel. Change driver op send_mlme() allowing to send a frame,
specifying an array of offsets to the CSA counters which should be
updated. For example, CSA offsets parameters should be specified when
sending Probe Response frames during CSA period.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/drivers/driver.h
src/drivers/driver_atheros.c
src/drivers/driver_hostap.c
src/drivers/driver_nl80211.c
wpa_supplicant/driver_i.h

index 6cafcb7..656f0a7 100644 (file)
@@ -649,7 +649,19 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
 {
        if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
                return 0;
-       return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0);
+       return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+                                      NULL, 0);
+}
+
+
+int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
+                             const void *msg, size_t len, int noack,
+                             const u16 *csa_offs, size_t csa_offs_len)
+{
+       if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
+               return 0;
+       return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+                                      csa_offs, csa_offs_len);
 }
 
 
index 82eaf3f..5a1e28e 100644 (file)
@@ -88,6 +88,9 @@ int hostapd_drv_set_key(const char *ifname,
                        const u8 *key, size_t key_len);
 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
                          const void *msg, size_t len, int noack);
+int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
+                             const void *msg, size_t len, int noack,
+                             const u16 *csa_offs, size_t csa_offs_len);
 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
                           const u8 *addr, int reason);
 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
index 262dc3f..09c4fa1 100644 (file)
@@ -1965,10 +1965,13 @@ struct wpa_driver_ops {
         * @noack: Do not wait for this frame to be acked (disable retries)
         * @freq: Frequency (in MHz) to send the frame on, or 0 to let the
         * driver decide
+        * @csa_offs: Array of CSA offsets or %NULL
+        * @csa_offs_len: Number of elements in csa_offs
         * Returns: 0 on success, -1 on failure
         */
        int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
-                        int noack, unsigned int freq);
+                        int noack, unsigned int freq, const u16 *csa_offs,
+                        size_t csa_offs_len);
 
        /**
         * update_ft_ies - Update FT (IEEE 802.11r) IEs
index ef14093..dbc1503 100644 (file)
@@ -1848,7 +1848,8 @@ static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params)
 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
 
 static int atheros_send_mgmt(void *priv, const u8 *frm, size_t data_len,
-                            int noack, unsigned int freq)
+                            int noack, unsigned int freq,
+                            const u16 *csa_offs, size_t csa_offs_len)
 {
        struct atheros_driver_data *drv = priv;
        u8 buf[1510];
index a7aa5ef..5bc7cc2 100644 (file)
@@ -258,7 +258,8 @@ static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr)
 
 
 static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack,
-                           unsigned int freq)
+                           unsigned int freq,
+                           const u16 *csa_offs, size_t csa_offs_len)
 {
        struct hostap_driver_data *drv = priv;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
@@ -307,7 +308,7 @@ static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
        pos += 2;
        memcpy(pos, data, data_len);
 
-       res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0);
+       res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0);
        if (res < 0) {
                wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - "
                           "failed: %d (%s)",
@@ -1045,7 +1046,7 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
        memcpy(mgmt.bssid, own_addr, ETH_ALEN);
        mgmt.u.deauth.reason_code = host_to_le16(reason);
        return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
-                               sizeof(mgmt.u.deauth), 0, 0);
+                               sizeof(mgmt.u.deauth), 0, 0, NULL, 0);
 }
 
 
@@ -1083,7 +1084,7 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
        memcpy(mgmt.bssid, own_addr, ETH_ALEN);
        mgmt.u.disassoc.reason_code = host_to_le16(reason);
        return  hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
-                                sizeof(mgmt.u.disassoc), 0, 0);
+                                sizeof(mgmt.u.disassoc), 0, 0, NULL, 0);
 }
 
 
@@ -1161,7 +1162,7 @@ static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
        os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
        os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
 
-       hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0);
+       hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0, NULL, 0);
 }
 
 
index f89bc24..05b0195 100644 (file)
@@ -176,7 +176,8 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 static int nl80211_send_frame_cmd(struct i802_bss *bss,
                                  unsigned int freq, unsigned int wait,
                                  const u8 *buf, size_t buf_len, u64 *cookie,
-                                 int no_cck, int no_ack, int offchanok);
+                                 int no_cck, int no_ack, int offchanok,
+                                 const u16 *csa_offs, size_t csa_offs_len);
 static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
                                               int report);
 
@@ -3093,7 +3094,9 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
                                         const void *data, size_t len,
                                         int encrypt, int noack,
                                         unsigned int freq, int no_cck,
-                                        int offchanok, unsigned int wait_time)
+                                        int offchanok, unsigned int wait_time,
+                                        const u16 *csa_offs,
+                                        size_t csa_offs_len)
 {
        struct wpa_driver_nl80211_data *drv = bss->drv;
        u64 cookie;
@@ -3119,7 +3122,8 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
 
        wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
        res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
-                                    &cookie, no_cck, noack, offchanok);
+                                    &cookie, no_cck, noack, offchanok,
+                                    csa_offs, csa_offs_len);
        if (res == 0 && !noack) {
                const struct ieee80211_mgmt *mgmt;
                u16 fc;
@@ -3145,7 +3149,9 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
                                        size_t data_len, int noack,
                                        unsigned int freq, int no_cck,
                                        int offchanok,
-                                       unsigned int wait_time)
+                                       unsigned int wait_time,
+                                       const u16 *csa_offs,
+                                       size_t csa_offs_len)
 {
        struct wpa_driver_nl80211_data *drv = bss->drv;
        struct ieee80211_mgmt *mgmt;
@@ -3175,7 +3181,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
                }
                return nl80211_send_frame_cmd(bss, freq, 0,
                                              data, data_len, NULL, 1, noack,
-                                             1);
+                                             1, csa_offs, csa_offs_len);
        }
 
        if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
@@ -3189,7 +3195,8 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
                                              wait_time,
                                              data, data_len,
                                              &drv->send_action_cookie,
-                                             no_cck, noack, offchanok);
+                                             no_cck, noack, offchanok,
+                                             csa_offs, csa_offs_len);
        }
 
        if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
@@ -3209,7 +3216,8 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
        wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
        return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
                                             noack, freq, no_cck, offchanok,
-                                            wait_time);
+                                            wait_time, csa_offs,
+                                            csa_offs_len);
 }
 
 
@@ -4248,7 +4256,7 @@ static int wpa_driver_nl80211_hapd_send_eapol(
        memcpy(pos, data, data_len);
 
        res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
-                                           0, 0, 0, 0);
+                                           0, 0, 0, 0, NULL, 0);
        if (res < 0) {
                wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
                           "failed: %d (%s)",
@@ -5439,7 +5447,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
        return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
                                            IEEE80211_HDRLEN +
                                            sizeof(mgmt.u.deauth), 0, 0, 0, 0,
-                                           0);
+                                           0, NULL, 0);
 }
 
 
@@ -5466,7 +5474,7 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
        return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
                                            IEEE80211_HDRLEN +
                                            sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
-                                           0);
+                                           0, NULL, 0);
 }
 
 
@@ -6125,7 +6133,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
                                  unsigned int freq, unsigned int wait,
                                  const u8 *buf, size_t buf_len,
                                  u64 *cookie_out, int no_cck, int no_ack,
-                                 int offchanok)
+                                 int offchanok, const u16 *csa_offs,
+                                 size_t csa_offs_len)
 {
        struct wpa_driver_nl80211_data *drv = bss->drv;
        struct nl_msg *msg;
@@ -6145,6 +6154,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
             nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) ||
            (no_cck && nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) ||
            (no_ack && nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK)) ||
+           (csa_offs && nla_put(msg, NL80211_ATTR_CSA_C_OFFSETS_TX,
+                                csa_offs_len * sizeof(u16), csa_offs)) ||
            nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf))
                goto fail;
 
@@ -6204,12 +6215,12 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
             !drv->use_monitor))
                ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
                                                   0, freq, no_cck, 1,
-                                                  wait_time);
+                                                  wait_time, NULL, 0);
        else
                ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
                                             24 + data_len,
                                             &drv->send_action_cookie,
-                                            no_cck, 0, 1);
+                                            no_cck, 0, 1, NULL, 0);
 
        os_free(buf);
        return ret;
@@ -6551,7 +6562,7 @@ static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
 {
        struct i802_bss *bss = priv;
        return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
-                                            0, 0, 0, 0);
+                                            0, 0, 0, 0, NULL, 0);
 }
 
 
@@ -6960,7 +6971,7 @@ static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
        os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
 
        if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
-                                        0, 0) < 0)
+                                        0, 0, NULL, 0) < 0)
                wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
                           "send poll frame");
 }
@@ -7280,11 +7291,13 @@ static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
 
 static int driver_nl80211_send_mlme(void *priv, const u8 *data,
                                    size_t data_len, int noack,
-                                   unsigned int freq)
+                                   unsigned int freq,
+                                   const u16 *csa_offs, size_t csa_offs_len)
 {
        struct i802_bss *bss = priv;
        return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
-                                           freq, 0, 0, 0);
+                                           freq, 0, 0, 0, csa_offs,
+                                           csa_offs_len);
 }
 
 
index 73768c7..f325154 100644 (file)
@@ -292,7 +292,7 @@ static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
        if (wpa_s->driver->send_mlme)
                return wpa_s->driver->send_mlme(wpa_s->drv_priv,
                                                data, data_len, noack,
-                                               freq);
+                                               freq, NULL, 0);
        return -1;
 }