mesh: Report HT operation mode to kernel
authorMasashi Honma <masashi.honma@gmail.com>
Fri, 5 Aug 2016 08:35:31 +0000 (17:35 +0900)
committerJouni Malinen <j@w1.fi>
Thu, 18 Aug 2016 17:46:15 +0000 (20:46 +0300)
Report HT operation mode to kernel to broadcast correct IE in beacon
(for example HT operation IE).

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/mesh.c

index ffe6f75..a5c5c1b 100644 (file)
@@ -1121,6 +1121,7 @@ struct wpa_driver_mesh_bss_params {
 #define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS          0x00000001
 #define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT    0x00000002
 #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS       0x00000004
 #define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS          0x00000001
 #define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT    0x00000002
 #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS       0x00000004
+#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE           0x00000008
        /*
         * TODO: Other mesh configuration parameters would go here.
         * See NL80211_MESHCONF_* for all the mesh config parameters.
        /*
         * TODO: Other mesh configuration parameters would go here.
         * See NL80211_MESHCONF_* for all the mesh config parameters.
@@ -1129,6 +1130,7 @@ struct wpa_driver_mesh_bss_params {
        int auto_plinks;
        int peer_link_timeout;
        int max_peer_links;
        int auto_plinks;
        int peer_link_timeout;
        int max_peer_links;
+       u16 ht_opmode;
 };
 
 struct wpa_driver_mesh_join_params {
 };
 
 struct wpa_driver_mesh_join_params {
index b801c9c..8d43c69 100644 (file)
@@ -200,6 +200,10 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
 
 static int i802_set_iface_flags(struct i802_bss *bss, int up);
 static int nl80211_set_param(void *priv, const char *param);
 
 static int i802_set_iface_flags(struct i802_bss *bss, int up);
 static int nl80211_set_param(void *priv, const char *param);
+#ifdef CONFIG_MESH
+static int nl80211_put_mesh_config(struct nl_msg *msg,
+                                  struct wpa_driver_mesh_bss_params *params);
+#endif /* CONFIG_MESH */
 
 
 /* Converts nl80211_chan_width to a common format */
 
 
 /* Converts nl80211_chan_width to a common format */
@@ -3480,6 +3484,37 @@ static int nl80211_put_dtim_period(struct nl_msg *msg, int dtim_period)
 }
 
 
 }
 
 
+#ifdef CONFIG_MESH
+static int nl80211_set_mesh_config(void *priv,
+                                  struct wpa_driver_mesh_bss_params *params)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       struct nl_msg *msg;
+       int ret;
+
+       msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MESH_CONFIG);
+       if (!msg)
+               return -1;
+
+       ret = nl80211_put_mesh_config(msg, params);
+       if (ret < 0) {
+               nlmsg_free(msg);
+               return ret;
+       }
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+       if (ret) {
+               wpa_printf(MSG_ERROR,
+                          "nl80211: Mesh config set failed: %d (%s)",
+                          ret, strerror(-ret));
+               return ret;
+       }
+       return 0;
+}
+#endif /* CONFIG_MESH */
+
+
 static int wpa_driver_nl80211_set_ap(void *priv,
                                     struct wpa_driver_ap_params *params)
 {
 static int wpa_driver_nl80211_set_ap(void *priv,
                                     struct wpa_driver_ap_params *params)
 {
@@ -3493,6 +3528,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
        int smps_mode;
        u32 suites[10], suite;
        u32 ver;
        int smps_mode;
        u32 suites[10], suite;
        u32 ver;
+#ifdef CONFIG_MESH
+       struct wpa_driver_mesh_bss_params mesh_params;
+#endif /* CONFIG_MESH */
 
        beacon_set = params->reenable ? 0 : bss->beacon_set;
 
 
        beacon_set = params->reenable ? 0 : bss->beacon_set;
 
@@ -3718,6 +3756,18 @@ static int wpa_driver_nl80211_set_ap(void *priv,
                        bss->bandwidth = params->freq->bandwidth;
                }
        }
                        bss->bandwidth = params->freq->bandwidth;
                }
        }
+
+#ifdef CONFIG_MESH
+       if (is_mesh_interface(drv->nlmode) && params->ht_opmode != -1) {
+               os_memset(&mesh_params, 0, sizeof(mesh_params));
+               mesh_params.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+               mesh_params.ht_opmode = params->ht_opmode;
+               ret = nl80211_set_mesh_config(priv, &mesh_params);
+               if (ret < 0)
+                       return ret;
+       }
+#endif /* CONFIG_MESH */
+
        return ret;
 fail:
        nlmsg_free(msg);
        return ret;
 fail:
        nlmsg_free(msg);
@@ -8441,6 +8491,12 @@ static int nl80211_put_mesh_config(struct nl_msg *msg,
                return -1;
        }
 
                return -1;
        }
 
+       if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE) &&
+           nla_put_u16(msg, NL80211_MESHCONF_HT_OPMODE, params->ht_opmode)) {
+               wpa_printf(MSG_ERROR, "nl80211: Failed to set HT_OP_MODE");
+               return -1;
+       }
+
        nla_nest_end(msg, container);
 
        return 0;
        nla_nest_end(msg, container);
 
        return 0;
index 3deeb49..741670b 100644 (file)
@@ -438,6 +438,8 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
                params.ies = wpa_s->ifmsh->mconf->rsn_ie;
                params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
                params.basic_rates = wpa_s->ifmsh->basic_rates;
                params.ies = wpa_s->ifmsh->mconf->rsn_ie;
                params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
                params.basic_rates = wpa_s->ifmsh->basic_rates;
+               params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+               params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode;
        }
 
        wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
        }
 
        wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",