mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
Couple of fixes:
* fix aggregation on mesh * fix late enabling of 4-addr mode * leave monitor SKBs with some headroom * limit band information for old applications * fix virt-wifi WARN_ON * fix memory leak in cfg80211 BSS list maintenance -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmD6kGIACgkQB8qZga/f l8RRuw/+Ox1Mf9WcZJms3t2yVVVgfPjoWWJYkay8ozzaTGDsZ9XxCm7jOuNNwNv2 NyeyGizaZDcD7Db2HYkMqh/VU4sYeC2ye4BSzyxFJkGjTxF2BD9NuxA+LeBEJNL2 /qZESfOa/1afenONoBYKWrWgiUbONjCekJbkGkBeyYSht0s2k6nh7nltiL+PH7eC 3PZBOs1k4+qXkrTblPyXYjXNbeBeZGRInEy8+MKQHns8StptsmRHqOiF75Nk0P3O mTnYSGjBJLZBfB13ZIHzRnxd+nb86EMM7r4hHHCxfseUFgQMe8ntQ5MTA+NORgZ7 Hi/IfklRG2ZNCj0Tq95GOEI4mX45He7I/awQ2ZitW0aq0rf+miYMi2uRS5t1G2R+ eyYZpfiOXPYE45PPzLCOiH8v492EHxMWtf8nRzgM9uRm3Inigi4hwsz9Uy8Rq610 8fE2tLUhNs942pl5GzKNoTuwhZMNEfR3MaInsj0XOYPWZwAz0z74bqxpboev1iHa f166+fPajPUOJfyh+0o2QUyMSbc6/M3mOukO3nDjHkIx+bft8d5EqU668C7h9mjG 8d0WaZdK4AUNL5oJmGJgfRfXcdjckZcJOO6umgLv5RWUhkOku/57UKLb6DrYdAIo m5DWpj7sEKPFH90ddoRZRKeF6lU9Mx1Zsa+tjdw8lZ2XyCkzyIU= =XUhh -----END PGP SIGNATURE----- Merge tag 'mac80211-for-net-2021-07-23' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Couple of fixes: * fix aggregation on mesh * fix late enabling of 4-addr mode * leave monitor SKBs with some headroom * limit band information for old applications * fix virt-wifi WARN_ON * fix memory leak in cfg80211 BSS list maintenance
This commit is contained in:
commit
1f22cf1349
@ -136,6 +136,29 @@ static struct ieee80211_supported_band band_5ghz = {
|
||||
/* Assigned at module init. Guaranteed locally-administered and unicast. */
|
||||
static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {};
|
||||
|
||||
static void virt_wifi_inform_bss(struct wiphy *wiphy)
|
||||
{
|
||||
u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);
|
||||
struct cfg80211_bss *informed_bss;
|
||||
static const struct {
|
||||
u8 tag;
|
||||
u8 len;
|
||||
u8 ssid[8];
|
||||
} __packed ssid = {
|
||||
.tag = WLAN_EID_SSID,
|
||||
.len = 8,
|
||||
.ssid = "VirtWifi",
|
||||
};
|
||||
|
||||
informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
|
||||
CFG80211_BSS_FTYPE_PRESP,
|
||||
fake_router_bssid, tsf,
|
||||
WLAN_CAPABILITY_ESS, 0,
|
||||
(void *)&ssid, sizeof(ssid),
|
||||
DBM_TO_MBM(-50), GFP_KERNEL);
|
||||
cfg80211_put_bss(wiphy, informed_bss);
|
||||
}
|
||||
|
||||
/* Called with the rtnl lock held. */
|
||||
static int virt_wifi_scan(struct wiphy *wiphy,
|
||||
struct cfg80211_scan_request *request)
|
||||
@ -156,28 +179,13 @@ static int virt_wifi_scan(struct wiphy *wiphy,
|
||||
/* Acquires and releases the rdev BSS lock. */
|
||||
static void virt_wifi_scan_result(struct work_struct *work)
|
||||
{
|
||||
struct {
|
||||
u8 tag;
|
||||
u8 len;
|
||||
u8 ssid[8];
|
||||
} __packed ssid = {
|
||||
.tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi",
|
||||
};
|
||||
struct cfg80211_bss *informed_bss;
|
||||
struct virt_wifi_wiphy_priv *priv =
|
||||
container_of(work, struct virt_wifi_wiphy_priv,
|
||||
scan_result.work);
|
||||
struct wiphy *wiphy = priv_to_wiphy(priv);
|
||||
struct cfg80211_scan_info scan_info = { .aborted = false };
|
||||
u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);
|
||||
|
||||
informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
|
||||
CFG80211_BSS_FTYPE_PRESP,
|
||||
fake_router_bssid, tsf,
|
||||
WLAN_CAPABILITY_ESS, 0,
|
||||
(void *)&ssid, sizeof(ssid),
|
||||
DBM_TO_MBM(-50), GFP_KERNEL);
|
||||
cfg80211_put_bss(wiphy, informed_bss);
|
||||
virt_wifi_inform_bss(wiphy);
|
||||
|
||||
/* Schedules work which acquires and releases the rtnl lock. */
|
||||
cfg80211_scan_done(priv->scan_request, &scan_info);
|
||||
@ -225,10 +233,12 @@ static int virt_wifi_connect(struct wiphy *wiphy, struct net_device *netdev,
|
||||
if (!could_schedule)
|
||||
return -EBUSY;
|
||||
|
||||
if (sme->bssid)
|
||||
if (sme->bssid) {
|
||||
ether_addr_copy(priv->connect_requested_bss, sme->bssid);
|
||||
else
|
||||
} else {
|
||||
virt_wifi_inform_bss(wiphy);
|
||||
eth_zero_addr(priv->connect_requested_bss);
|
||||
}
|
||||
|
||||
wiphy_debug(wiphy, "connect\n");
|
||||
|
||||
@ -241,11 +251,13 @@ static void virt_wifi_connect_complete(struct work_struct *work)
|
||||
struct virt_wifi_netdev_priv *priv =
|
||||
container_of(work, struct virt_wifi_netdev_priv, connect.work);
|
||||
u8 *requested_bss = priv->connect_requested_bss;
|
||||
bool has_addr = !is_zero_ether_addr(requested_bss);
|
||||
bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid);
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
|
||||
if (!priv->is_up || (has_addr && !right_addr))
|
||||
if (is_zero_ether_addr(requested_bss))
|
||||
requested_bss = NULL;
|
||||
|
||||
if (!priv->is_up || (requested_bss && !right_addr))
|
||||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
else
|
||||
priv->is_connected = true;
|
||||
|
@ -152,6 +152,8 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
||||
struct vif_params *params)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
int ret;
|
||||
|
||||
ret = ieee80211_if_change_type(sdata, type);
|
||||
@ -162,7 +164,24 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
||||
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
|
||||
ieee80211_check_fast_rx_iface(sdata);
|
||||
} else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) {
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
|
||||
if (params->use_4addr == ifmgd->use_4addr)
|
||||
return 0;
|
||||
|
||||
sdata->u.mgd.use_4addr = params->use_4addr;
|
||||
if (!ifmgd->associated)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get(sdata, ifmgd->bssid);
|
||||
if (sta)
|
||||
drv_sta_set_4addr(local, sdata, &sta->sta,
|
||||
params->use_4addr);
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
if (params->use_4addr)
|
||||
ieee80211_send_4addr_nullfunc(local, sdata);
|
||||
}
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
||||
|
@ -2201,6 +2201,8 @@ void ieee80211_dynamic_ps_timer(struct timer_list *t);
|
||||
void ieee80211_send_nullfunc(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
bool powersave);
|
||||
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
|
||||
|
||||
|
@ -1095,8 +1095,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
}
|
||||
|
||||
static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_hdr *nullfunc;
|
||||
|
@ -730,7 +730,8 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local,
|
||||
* Need to make a copy and possibly remove radiotap header
|
||||
* and FCS from the original.
|
||||
*/
|
||||
skb = skb_copy_expand(*origskb, needed_headroom, 0, GFP_ATOMIC);
|
||||
skb = skb_copy_expand(*origskb, needed_headroom + NET_SKB_PAD,
|
||||
0, GFP_ATOMIC);
|
||||
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
@ -1147,6 +1147,29 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
|
||||
return queued;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rate_control_ref *ref = sdata->local->rate_ctrl;
|
||||
u16 tid;
|
||||
|
||||
if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER))
|
||||
return;
|
||||
|
||||
if (!sta || !sta->sta.ht_cap.ht_supported ||
|
||||
!sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO ||
|
||||
skb->protocol == sdata->control_port_protocol)
|
||||
return;
|
||||
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (likely(sta->ampdu_mlme.tid_tx[tid]))
|
||||
return;
|
||||
|
||||
ieee80211_start_tx_ba_session(&sta->sta, tid, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialises @tx
|
||||
* pass %NULL for the station if unknown, a valid pointer if known
|
||||
@ -1160,6 +1183,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
bool aggr_check = false;
|
||||
int tid;
|
||||
|
||||
memset(tx, 0, sizeof(*tx));
|
||||
@ -1188,8 +1212,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
||||
} else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
|
||||
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
|
||||
}
|
||||
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
|
||||
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) {
|
||||
tx->sta = sta_info_get(sdata, hdr->addr1);
|
||||
aggr_check = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
|
||||
@ -1199,8 +1225,12 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
|
||||
tid = ieee80211_get_tid(hdr);
|
||||
|
||||
tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
|
||||
if (!tid_tx && aggr_check) {
|
||||
ieee80211_aggr_check(sdata, tx->sta, skb);
|
||||
tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
|
||||
}
|
||||
|
||||
if (tid_tx) {
|
||||
bool queued;
|
||||
|
||||
@ -4120,29 +4150,6 @@ void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_txq_schedule_start);
|
||||
|
||||
static void
|
||||
ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rate_control_ref *ref = sdata->local->rate_ctrl;
|
||||
u16 tid;
|
||||
|
||||
if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER))
|
||||
return;
|
||||
|
||||
if (!sta || !sta->sta.ht_cap.ht_supported ||
|
||||
!sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO ||
|
||||
skb->protocol == sdata->control_port_protocol)
|
||||
return;
|
||||
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (likely(sta->ampdu_mlme.tid_tx[tid]))
|
||||
return;
|
||||
|
||||
ieee80211_start_tx_ba_session(&sta->sta, tid, 0);
|
||||
}
|
||||
|
||||
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
u32 info_flags,
|
||||
|
@ -2351,7 +2351,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||
goto nla_put_failure;
|
||||
|
||||
for (band = state->band_start;
|
||||
band < NUM_NL80211_BANDS; band++) {
|
||||
band < (state->split ?
|
||||
NUM_NL80211_BANDS :
|
||||
NL80211_BAND_60GHZ + 1);
|
||||
band++) {
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
/* omit higher bands for ancient software */
|
||||
|
@ -1754,16 +1754,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
||||
* be grouped with this beacon for updates ...
|
||||
*/
|
||||
if (!cfg80211_combine_bsses(rdev, new)) {
|
||||
kfree(new);
|
||||
bss_ref_put(rdev, new);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
|
||||
if (rdev->bss_entries >= bss_entries_limit &&
|
||||
!cfg80211_bss_expire_oldest(rdev)) {
|
||||
if (!list_empty(&new->hidden_list))
|
||||
list_del(&new->hidden_list);
|
||||
kfree(new);
|
||||
bss_ref_put(rdev, new);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user