cfg80211: save multi-bssid properties

When the new IEs are generated, the multiple BSSID elements
are not saved. Save aside properties that are needed later
for PS.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Sara Sharon 2019-01-22 09:50:50 +02:00 committed by Johannes Berg
parent 7ece9c372b
commit 0cd01efb03
2 changed files with 53 additions and 21 deletions

View File

@ -2038,6 +2038,8 @@ struct cfg80211_bss_ies {
* @signal: signal strength value (type depends on the wiphy's signal_type) * @signal: signal strength value (type depends on the wiphy's signal_type)
* @chains: bitmask for filled values in @chain_signal. * @chains: bitmask for filled values in @chain_signal.
* @chain_signal: per-chain signal strength of last received BSS in dBm. * @chain_signal: per-chain signal strength of last received BSS in dBm.
* @bssid_index: index in the multiple BSS set
* @max_bssid_indicator: max number of members in the BSS set
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/ */
struct cfg80211_bss { struct cfg80211_bss {
@ -2061,6 +2063,9 @@ struct cfg80211_bss {
u8 chains; u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS]; s8 chain_signal[IEEE80211_MAX_CHAINS];
u8 bssid_index;
u8 max_bssid_indicator;
u8 priv[0] __aligned(sizeof(void *)); u8 priv[0] __aligned(sizeof(void *));
}; };

View File

@ -1022,11 +1022,16 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
return true; return true;
} }
struct cfg80211_non_tx_bss {
struct cfg80211_bss *tx_bss;
u8 max_bssid_indicator;
u8 bssid_index;
};
/* Returned bss is reference counted and must be cleaned up appropriately. */ /* Returned bss is reference counted and must be cleaned up appropriately. */
static struct cfg80211_internal_bss * static struct cfg80211_internal_bss *
cfg80211_bss_update(struct cfg80211_registered_device *rdev, cfg80211_bss_update(struct cfg80211_registered_device *rdev,
struct cfg80211_internal_bss *tmp, struct cfg80211_internal_bss *tmp,
struct cfg80211_bss *trans_bss,
bool signal_valid) bool signal_valid)
{ {
struct cfg80211_internal_bss *found = NULL; struct cfg80211_internal_bss *found = NULL;
@ -1126,6 +1131,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
memcpy(found->pub.chain_signal, tmp->pub.chain_signal, memcpy(found->pub.chain_signal, tmp->pub.chain_signal,
IEEE80211_MAX_CHAINS); IEEE80211_MAX_CHAINS);
ether_addr_copy(found->parent_bssid, tmp->parent_bssid); ether_addr_copy(found->parent_bssid, tmp->parent_bssid);
found->pub.max_bssid_indicator = tmp->pub.max_bssid_indicator;
found->pub.bssid_index = tmp->pub.bssid_index;
} else { } else {
struct cfg80211_internal_bss *new; struct cfg80211_internal_bss *new;
struct cfg80211_internal_bss *hidden; struct cfg80211_internal_bss *hidden;
@ -1185,13 +1192,13 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
} }
/* This must be before the call to bss_ref_get */ /* This must be before the call to bss_ref_get */
if (trans_bss) { if (tmp->pub.transmitted_bss) {
struct cfg80211_internal_bss *pbss = struct cfg80211_internal_bss *pbss =
container_of(trans_bss, container_of(tmp->pub.transmitted_bss,
struct cfg80211_internal_bss, struct cfg80211_internal_bss,
pub); pub);
new->pub.transmitted_bss = trans_bss; new->pub.transmitted_bss = tmp->pub.transmitted_bss;
bss_ref_get(rdev, pbss); bss_ref_get(rdev, pbss);
} }
@ -1289,7 +1296,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
enum cfg80211_bss_frame_type ftype, enum cfg80211_bss_frame_type ftype,
const u8 *bssid, u64 tsf, u16 capability, const u8 *bssid, u64 tsf, u16 capability,
u16 beacon_interval, const u8 *ie, size_t ielen, u16 beacon_interval, const u8 *ie, size_t ielen,
struct cfg80211_bss *trans_bss, struct cfg80211_non_tx_bss *non_tx_data,
gfp_t gfp) gfp_t gfp)
{ {
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@ -1318,6 +1325,11 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
tmp.pub.beacon_interval = beacon_interval; tmp.pub.beacon_interval = beacon_interval;
tmp.pub.capability = capability; tmp.pub.capability = capability;
tmp.ts_boottime = data->boottime_ns; tmp.ts_boottime = data->boottime_ns;
if (non_tx_data) {
tmp.pub.transmitted_bss = non_tx_data->tx_bss;
tmp.pub.bssid_index = non_tx_data->bssid_index;
tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator;
}
/* /*
* If we do not know here whether the IEs are from a Beacon or Probe * If we do not know here whether the IEs are from a Beacon or Probe
@ -1350,8 +1362,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
signal_valid = abs(data->chan->center_freq - channel->center_freq) <= signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
wiphy->max_adj_channel_rssi_comp; wiphy->max_adj_channel_rssi_comp;
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss, res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
signal_valid);
if (!res) if (!res)
return NULL; return NULL;
@ -1365,11 +1376,12 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
regulatory_hint_found_beacon(wiphy, channel, gfp); regulatory_hint_found_beacon(wiphy, channel, gfp);
} }
if (trans_bss) { if (non_tx_data && non_tx_data->tx_bss) {
/* this is a nontransmitting bss, we need to add it to /* this is a nontransmitting bss, we need to add it to
* transmitting bss' list if it is not there * transmitting bss' list if it is not there
*/ */
if (cfg80211_add_nontrans_list(trans_bss, &res->pub)) { if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
&res->pub)) {
if (__cfg80211_unlink_bss(rdev, res)) if (__cfg80211_unlink_bss(rdev, res))
rdev->bss_generation++; rdev->bss_generation++;
} }
@ -1386,7 +1398,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
const u8 *bssid, u64 tsf, const u8 *bssid, u64 tsf,
u16 beacon_interval, const u8 *ie, u16 beacon_interval, const u8 *ie,
size_t ielen, size_t ielen,
struct cfg80211_bss *trans_bss, struct cfg80211_non_tx_bss *non_tx_data,
gfp_t gfp) gfp_t gfp)
{ {
const u8 *mbssid_index_ie; const u8 *mbssid_index_ie;
@ -1397,7 +1409,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
u16 capability; u16 capability;
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
if (!trans_bss) if (!non_tx_data)
return; return;
if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen)) if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
return; return;
@ -1439,8 +1451,12 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
continue; continue;
} }
cfg80211_gen_new_bssid(bssid, elem->data[0], non_tx_data->bssid_index = mbssid_index_ie[2];
mbssid_index_ie[2], non_tx_data->max_bssid_indicator = elem->data[0];
cfg80211_gen_new_bssid(bssid,
non_tx_data->max_bssid_indicator,
non_tx_data->bssid_index,
new_bssid); new_bssid);
memset(new_ie, 0, IEEE80211_MAX_DATA_LEN); memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
new_ie_len = cfg80211_gen_new_ie(ie, ielen, sub->data, new_ie_len = cfg80211_gen_new_ie(ie, ielen, sub->data,
@ -1457,7 +1473,8 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
beacon_interval, beacon_interval,
new_ie, new_ie,
new_ie_len, new_ie_len,
trans_bss, gfp); non_tx_data,
gfp);
if (!bss) if (!bss)
break; break;
cfg80211_put_bss(wiphy, bss); cfg80211_put_bss(wiphy, bss);
@ -1476,12 +1493,15 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
gfp_t gfp) gfp_t gfp)
{ {
struct cfg80211_bss *res; struct cfg80211_bss *res;
struct cfg80211_non_tx_bss non_tx_data;
res = cfg80211_inform_single_bss_data(wiphy, data, ftype, bssid, tsf, res = cfg80211_inform_single_bss_data(wiphy, data, ftype, bssid, tsf,
capability, beacon_interval, ie, capability, beacon_interval, ie,
ielen, NULL, gfp); ielen, NULL, gfp);
non_tx_data.tx_bss = res;
cfg80211_parse_mbssid_data(wiphy, data, ftype, bssid, tsf, cfg80211_parse_mbssid_data(wiphy, data, ftype, bssid, tsf,
beacon_interval, ie, ielen, res, gfp); beacon_interval, ie, ielen, &non_tx_data,
gfp);
return res; return res;
} }
EXPORT_SYMBOL(cfg80211_inform_bss_data); EXPORT_SYMBOL(cfg80211_inform_bss_data);
@ -1490,7 +1510,7 @@ static void
cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy, cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
struct cfg80211_inform_bss *data, struct cfg80211_inform_bss *data,
struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_mgmt *mgmt, size_t len,
struct cfg80211_bss *trans_bss, struct cfg80211_non_tx_bss *non_tx_data,
gfp_t gfp) gfp_t gfp)
{ {
enum cfg80211_bss_frame_type ftype; enum cfg80211_bss_frame_type ftype;
@ -1504,7 +1524,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
cfg80211_parse_mbssid_data(wiphy, data, ftype, mgmt->bssid, cfg80211_parse_mbssid_data(wiphy, data, ftype, mgmt->bssid,
le64_to_cpu(mgmt->u.probe_resp.timestamp), le64_to_cpu(mgmt->u.probe_resp.timestamp),
le16_to_cpu(mgmt->u.probe_resp.beacon_int), le16_to_cpu(mgmt->u.probe_resp.beacon_int),
ie, ielen, trans_bss, gfp); ie, ielen, non_tx_data, gfp);
} }
static void static void
@ -1594,7 +1614,7 @@ static struct cfg80211_bss *
cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy, cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
struct cfg80211_inform_bss *data, struct cfg80211_inform_bss *data,
struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_mgmt *mgmt, size_t len,
struct cfg80211_bss *trans_bss, struct cfg80211_non_tx_bss *non_tx_data,
gfp_t gfp) gfp_t gfp)
{ {
struct cfg80211_internal_bss tmp = {}, *res; struct cfg80211_internal_bss tmp = {}, *res;
@ -1653,11 +1673,15 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
tmp.pub.chains = data->chains; tmp.pub.chains = data->chains;
memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS); memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS);
ether_addr_copy(tmp.parent_bssid, data->parent_bssid); ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
if (non_tx_data) {
tmp.pub.transmitted_bss = non_tx_data->tx_bss;
tmp.pub.bssid_index = non_tx_data->bssid_index;
tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator;
}
signal_valid = abs(data->chan->center_freq - channel->center_freq) <= signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
wiphy->max_adj_channel_rssi_comp; wiphy->max_adj_channel_rssi_comp;
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss, res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
signal_valid);
if (!res) if (!res)
return NULL; return NULL;
@ -1687,6 +1711,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
const struct cfg80211_bss_ies *ies1, *ies2; const struct cfg80211_bss_ies *ies1, *ies2;
size_t ielen = len - offsetof(struct ieee80211_mgmt, size_t ielen = len - offsetof(struct ieee80211_mgmt,
u.probe_resp.variable); u.probe_resp.variable);
struct cfg80211_non_tx_bss non_tx_data;
res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt, res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt,
len, NULL, gfp); len, NULL, gfp);
@ -1697,8 +1722,10 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
!cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen)) !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
return res; return res;
non_tx_data.tx_bss = res;
/* process each non-transmitting bss */ /* process each non-transmitting bss */
cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, res, gfp); cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len,
&non_tx_data, gfp);
/* check if the res has other nontransmitting bss which is not /* check if the res has other nontransmitting bss which is not
* in MBSSID IE * in MBSSID IE