]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Optimize memory use in nl80211_get_assoc_freq()
authorJouni Malinen <j@w1.fi>
Sat, 3 Dec 2016 20:37:41 +0000 (22:37 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 3 Dec 2016 20:37:41 +0000 (22:37 +0200)
Do not use the generic bss_info_handler() design to fetch all scan
results into temporary memory buffer. Instead, use a separate BSS info
handler that fetches the requested information without fully parsing the
BSS entries and without allocating any memory for collecting all the
results.

This is also simplifying bss_info_handler() and nl80211_parse_bss_info()
design by getting rid of the special case that was used only for
nl80211_get_assoc_freq() and not normal scan result fetching.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_scan.c

index 4f7069bf28c89d0e91230b74c773a6bbf9fb4613..6bd984d5697fc377554a473137034a755f33d850 100644 (file)
@@ -1181,16 +1181,70 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
 }
 
 
+struct nl80211_get_assoc_freq_arg {
+       struct wpa_driver_nl80211_data *drv;
+       unsigned int assoc_freq;
+       unsigned int ibss_freq;
+       u8 assoc_bssid[ETH_ALEN];
+};
+
+static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *bss[NL80211_BSS_MAX + 1];
+       static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+               [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
+               [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+               [NL80211_BSS_STATUS] = { .type = NLA_U32 },
+       };
+       struct nl80211_get_assoc_freq_arg *ctx = arg;
+       enum nl80211_bss_status status;
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+       if (!tb[NL80211_ATTR_BSS] ||
+           nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
+                            bss_policy) ||
+           !bss[NL80211_BSS_STATUS])
+               return NL_SKIP;
+
+       status = nla_get_u32(bss[NL80211_BSS_STATUS]);
+       if (status == NL80211_BSS_STATUS_ASSOCIATED &&
+           bss[NL80211_BSS_FREQUENCY]) {
+               ctx->assoc_freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
+               wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
+                          ctx->assoc_freq);
+       }
+       if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
+           bss[NL80211_BSS_FREQUENCY]) {
+               ctx->ibss_freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
+               wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
+                          ctx->ibss_freq);
+       }
+       if (status == NL80211_BSS_STATUS_ASSOCIATED &&
+           bss[NL80211_BSS_BSSID]) {
+               os_memcpy(ctx->assoc_bssid,
+                         nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
+               wpa_printf(MSG_DEBUG, "nl80211: Associated with "
+                          MACSTR, MAC2STR(ctx->assoc_bssid));
+       }
+
+       return NL_SKIP;
+}
+
+
 unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
 {
        struct nl_msg *msg;
        int ret;
-       struct nl80211_bss_info_arg arg;
+       struct nl80211_get_assoc_freq_arg arg;
 
        msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
        os_memset(&arg, 0, sizeof(arg));
        arg.drv = drv;
-       ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
+       ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
+                                &arg);
        if (ret == 0) {
                unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
                        arg.ibss_freq : arg.assoc_freq;
index 8d12978bd8817bb1216c0da775cfabf14d2382ec..3e33158ae92931e11374bdd9cc24d966f0296b2a 100644 (file)
@@ -282,15 +282,6 @@ int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
 
 /* driver_nl80211_scan.c */
 
-struct nl80211_bss_info_arg {
-       struct wpa_driver_nl80211_data *drv;
-       struct wpa_scan_results *res;
-       unsigned int assoc_freq;
-       unsigned int ibss_freq;
-       u8 assoc_bssid[ETH_ALEN];
-};
-
-int bss_info_handler(struct nl_msg *msg, void *arg);
 void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx);
 int wpa_driver_nl80211_scan(struct i802_bss *bss,
                            struct wpa_driver_scan_params *params);
index 385ba6b2a8b10e3c38ace37277b7c70a973ea9ac..43ed2b74cf35561a460265082ec6f8961d3839f2 100644 (file)
@@ -628,7 +628,7 @@ static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
 
 static struct wpa_scan_res *
 nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
-                      struct nl_msg *msg, struct nl80211_bss_info_arg *_arg)
+                      struct nl_msg *msg)
 {
        struct nlattr *tb[NL80211_ATTR_MAX + 1];
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
@@ -658,33 +658,6 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
        if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
                             bss_policy))
                return NULL;
-       if (bss[NL80211_BSS_STATUS] && _arg) {
-               enum nl80211_bss_status status;
-               status = nla_get_u32(bss[NL80211_BSS_STATUS]);
-               if (status == NL80211_BSS_STATUS_ASSOCIATED &&
-                   bss[NL80211_BSS_FREQUENCY]) {
-                       _arg->assoc_freq =
-                               nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
-                       wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
-                                  _arg->assoc_freq);
-               }
-               if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
-                   bss[NL80211_BSS_FREQUENCY]) {
-                       _arg->ibss_freq =
-                               nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
-                       wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
-                                  _arg->ibss_freq);
-               }
-               if (status == NL80211_BSS_STATUS_ASSOCIATED &&
-                   bss[NL80211_BSS_BSSID]) {
-                       os_memcpy(_arg->assoc_bssid,
-                                 nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
-                       wpa_printf(MSG_DEBUG, "nl80211: Associated with "
-                                  MACSTR, MAC2STR(_arg->assoc_bssid));
-               }
-       }
-       if (_arg && !_arg->res)
-               return NULL;
        if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
                ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
                ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
@@ -761,14 +734,19 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
 }
 
 
-int bss_info_handler(struct nl_msg *msg, void *arg)
+struct nl80211_bss_info_arg {
+       struct wpa_driver_nl80211_data *drv;
+       struct wpa_scan_results *res;
+};
+
+static int bss_info_handler(struct nl_msg *msg, void *arg)
 {
        struct nl80211_bss_info_arg *_arg = arg;
        struct wpa_scan_results *res = _arg->res;
        struct wpa_scan_res **tmp;
        struct wpa_scan_res *r;
 
-       r = nl80211_parse_bss_info(_arg->drv, msg, _arg);
+       r = nl80211_parse_bss_info(_arg->drv, msg);
        if (!r)
                return NL_SKIP;
 
@@ -920,7 +898,7 @@ static int nl80211_dump_scan_handler(struct nl_msg *msg, void *arg)
        struct nl80211_dump_scan_ctx *ctx = arg;
        struct wpa_scan_res *r;
 
-       r = nl80211_parse_bss_info(ctx->drv, msg, NULL);
+       r = nl80211_parse_bss_info(ctx->drv, msg);
        if (!r)
                return NL_SKIP;
        wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s",