nl80211: Optimize memory use in nl80211_get_assoc_freq()
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>
This commit is contained in:
parent
da2c284169
commit
a1fce3911f
3 changed files with 65 additions and 42 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue