cfg80211: add bss_type and privacy arguments in cfg80211_get_bss()
802.11ad adds new a network type (PBSS) and changes the capability field interpretation for the DMG (60G) band. The same 2 bits that were interpreted as "ESS" and "IBSS" before are re-used as a 2-bit field with 3 valid values (and 1 reserved). Valid values are: "IBSS", "PBSS" (new) and "AP". In order to get the BSS struct for the new PBSS networks, change the cfg80211_get_bss() function to take a new enum ieee80211_bss_type argument with the valid network types, as "capa_mask" and "capa_val" no longer work correctly (the search must be band-aware now.) The remaining bits in "capa_mask" and "capa_val" are used only for privacy matching so replace those two with a privacy enum as well. Signed-off-by: Dedy Lansky <dlansky@codeaurora.org> [rewrite commit log, tiny fixes] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:

committed by
Johannes Berg

parent
76a70e9c4b
commit
6eb1813764
@@ -30,7 +30,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
return;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
|
||||
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
||||
IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY);
|
||||
|
||||
if (WARN_ON(!bss))
|
||||
return;
|
||||
|
@@ -229,7 +229,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
return -EALREADY;
|
||||
|
||||
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY_ANY);
|
||||
if (!req.bss)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -296,7 +297,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
rdev->wiphy.vht_capa_mod_mask);
|
||||
|
||||
req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY_ANY);
|
||||
if (!req->bss)
|
||||
return -ENOENT;
|
||||
|
||||
|
@@ -531,24 +531,78 @@ static int cmp_bss(struct cfg80211_bss *a,
|
||||
}
|
||||
}
|
||||
|
||||
static bool cfg80211_bss_type_match(u16 capability,
|
||||
enum ieee80211_band band,
|
||||
enum ieee80211_bss_type bss_type)
|
||||
{
|
||||
bool ret = true;
|
||||
u16 mask, val;
|
||||
|
||||
if (bss_type == IEEE80211_BSS_TYPE_ANY)
|
||||
return ret;
|
||||
|
||||
if (band == IEEE80211_BAND_60GHZ) {
|
||||
mask = WLAN_CAPABILITY_DMG_TYPE_MASK;
|
||||
switch (bss_type) {
|
||||
case IEEE80211_BSS_TYPE_ESS:
|
||||
val = WLAN_CAPABILITY_DMG_TYPE_AP;
|
||||
break;
|
||||
case IEEE80211_BSS_TYPE_PBSS:
|
||||
val = WLAN_CAPABILITY_DMG_TYPE_PBSS;
|
||||
break;
|
||||
case IEEE80211_BSS_TYPE_IBSS:
|
||||
val = WLAN_CAPABILITY_DMG_TYPE_IBSS;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
mask = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS;
|
||||
switch (bss_type) {
|
||||
case IEEE80211_BSS_TYPE_ESS:
|
||||
val = WLAN_CAPABILITY_ESS;
|
||||
break;
|
||||
case IEEE80211_BSS_TYPE_IBSS:
|
||||
val = WLAN_CAPABILITY_IBSS;
|
||||
break;
|
||||
case IEEE80211_BSS_TYPE_MBSS:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ((capability & mask) == val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returned bss is reference counted and must be cleaned up appropriately. */
|
||||
struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *channel,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
u16 capa_mask, u16 capa_val)
|
||||
enum ieee80211_bss_type bss_type,
|
||||
enum ieee80211_privacy privacy)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct cfg80211_internal_bss *bss, *res = NULL;
|
||||
unsigned long now = jiffies;
|
||||
int bss_privacy;
|
||||
|
||||
trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask,
|
||||
capa_val);
|
||||
trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, bss_type,
|
||||
privacy);
|
||||
|
||||
spin_lock_bh(&rdev->bss_lock);
|
||||
|
||||
list_for_each_entry(bss, &rdev->bss_list, list) {
|
||||
if ((bss->pub.capability & capa_mask) != capa_val)
|
||||
if (!cfg80211_bss_type_match(bss->pub.capability,
|
||||
bss->pub.channel->band, bss_type))
|
||||
continue;
|
||||
|
||||
bss_privacy = (bss->pub.capability & WLAN_CAPABILITY_PRIVACY);
|
||||
if ((privacy == IEEE80211_PRIVACY_ON && !bss_privacy) ||
|
||||
(privacy == IEEE80211_PRIVACY_OFF && bss_privacy))
|
||||
continue;
|
||||
if (channel && bss->pub.channel != channel)
|
||||
continue;
|
||||
@@ -896,6 +950,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
||||
struct cfg80211_bss_ies *ies;
|
||||
struct ieee80211_channel *channel;
|
||||
struct cfg80211_internal_bss tmp = {}, *res;
|
||||
int bss_type;
|
||||
bool signal_valid;
|
||||
|
||||
if (WARN_ON(!wiphy))
|
||||
@@ -950,8 +1005,15 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
||||
regulatory_hint_found_beacon(wiphy, channel, gfp);
|
||||
if (channel->band == IEEE80211_BAND_60GHZ) {
|
||||
bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
|
||||
if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
|
||||
bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
|
||||
regulatory_hint_found_beacon(wiphy, channel, gfp);
|
||||
} else {
|
||||
if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
||||
regulatory_hint_found_beacon(wiphy, channel, gfp);
|
||||
}
|
||||
|
||||
trace_cfg80211_return_bss(&res->pub);
|
||||
/* cfg80211_bss_update gives us a referenced result */
|
||||
@@ -973,6 +1035,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
||||
bool signal_valid;
|
||||
size_t ielen = len - offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable);
|
||||
int bss_type;
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
|
||||
offsetof(struct ieee80211_mgmt, u.beacon.variable));
|
||||
@@ -1025,8 +1088,15 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
||||
regulatory_hint_found_beacon(wiphy, channel, gfp);
|
||||
if (channel->band == IEEE80211_BAND_60GHZ) {
|
||||
bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
|
||||
if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
|
||||
bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
|
||||
regulatory_hint_found_beacon(wiphy, channel, gfp);
|
||||
} else {
|
||||
if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
||||
regulatory_hint_found_beacon(wiphy, channel, gfp);
|
||||
}
|
||||
|
||||
trace_cfg80211_return_bss(&res->pub);
|
||||
/* cfg80211_bss_update gives us a referenced result */
|
||||
|
@@ -257,19 +257,15 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct cfg80211_bss *bss;
|
||||
u16 capa = WLAN_CAPABILITY_ESS;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (wdev->conn->params.privacy)
|
||||
capa |= WLAN_CAPABILITY_PRIVACY;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
|
||||
wdev->conn->params.bssid,
|
||||
wdev->conn->params.ssid,
|
||||
wdev->conn->params.ssid_len,
|
||||
WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
|
||||
capa);
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY(wdev->conn->params.privacy));
|
||||
if (!bss)
|
||||
return NULL;
|
||||
|
||||
@@ -637,8 +633,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect);
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
wdev->ssid, wdev->ssid_len,
|
||||
WLAN_CAPABILITY_ESS,
|
||||
WLAN_CAPABILITY_ESS);
|
||||
IEEE80211_BSS_TYPE_ESS,
|
||||
IEEE80211_PRIVACY_ANY);
|
||||
if (bss)
|
||||
cfg80211_hold_bss(bss_from_pub(bss));
|
||||
}
|
||||
@@ -795,8 +791,8 @@ void cfg80211_roamed(struct net_device *dev,
|
||||
struct cfg80211_bss *bss;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid,
|
||||
wdev->ssid_len, WLAN_CAPABILITY_ESS,
|
||||
WLAN_CAPABILITY_ESS);
|
||||
wdev->ssid_len,
|
||||
IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
|
||||
if (WARN_ON(!bss))
|
||||
return;
|
||||
|
||||
|
@@ -2636,28 +2636,30 @@ DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_stopped,
|
||||
TRACE_EVENT(cfg80211_get_bss,
|
||||
TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
|
||||
const u8 *bssid, const u8 *ssid, size_t ssid_len,
|
||||
u16 capa_mask, u16 capa_val),
|
||||
TP_ARGS(wiphy, channel, bssid, ssid, ssid_len, capa_mask, capa_val),
|
||||
enum ieee80211_bss_type bss_type,
|
||||
enum ieee80211_privacy privacy),
|
||||
TP_ARGS(wiphy, channel, bssid, ssid, ssid_len, bss_type, privacy),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
CHAN_ENTRY
|
||||
MAC_ENTRY(bssid)
|
||||
__dynamic_array(u8, ssid, ssid_len)
|
||||
__field(u16, capa_mask)
|
||||
__field(u16, capa_val)
|
||||
__field(enum ieee80211_bss_type, bss_type)
|
||||
__field(enum ieee80211_privacy, privacy)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
CHAN_ASSIGN(channel);
|
||||
MAC_ASSIGN(bssid, bssid);
|
||||
memcpy(__get_dynamic_array(ssid), ssid, ssid_len);
|
||||
__entry->capa_mask = capa_mask;
|
||||
__entry->capa_val = capa_val;
|
||||
__entry->bss_type = bss_type;
|
||||
__entry->privacy = privacy;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT ", buf: %#.2x, "
|
||||
"capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG,
|
||||
MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0],
|
||||
__entry->capa_mask, __entry->capa_val)
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT
|
||||
", buf: %#.2x, bss_type: %d, privacy: %d",
|
||||
WIPHY_PR_ARG, CHAN_PR_ARG, MAC_PR_ARG(bssid),
|
||||
((u8 *)__get_dynamic_array(ssid))[0], __entry->bss_type,
|
||||
__entry->privacy)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_inform_bss_width_frame,
|
||||
|
Reference in New Issue
Block a user