Skip to content

Commit 1f22cf1

Browse files
committed
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
2 parents 15bbf8b + f9a5c35 commit 1f22cf1

File tree

8 files changed

+95
-53
lines changed

8 files changed

+95
-53
lines changed

drivers/net/wireless/virt_wifi.c

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,29 @@ static struct ieee80211_supported_band band_5ghz = {
136136
/* Assigned at module init. Guaranteed locally-administered and unicast. */
137137
static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {};
138138

139+
static void virt_wifi_inform_bss(struct wiphy *wiphy)
140+
{
141+
u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);
142+
struct cfg80211_bss *informed_bss;
143+
static const struct {
144+
u8 tag;
145+
u8 len;
146+
u8 ssid[8];
147+
} __packed ssid = {
148+
.tag = WLAN_EID_SSID,
149+
.len = 8,
150+
.ssid = "VirtWifi",
151+
};
152+
153+
informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
154+
CFG80211_BSS_FTYPE_PRESP,
155+
fake_router_bssid, tsf,
156+
WLAN_CAPABILITY_ESS, 0,
157+
(void *)&ssid, sizeof(ssid),
158+
DBM_TO_MBM(-50), GFP_KERNEL);
159+
cfg80211_put_bss(wiphy, informed_bss);
160+
}
161+
139162
/* Called with the rtnl lock held. */
140163
static int virt_wifi_scan(struct wiphy *wiphy,
141164
struct cfg80211_scan_request *request)
@@ -156,28 +179,13 @@ static int virt_wifi_scan(struct wiphy *wiphy,
156179
/* Acquires and releases the rdev BSS lock. */
157180
static void virt_wifi_scan_result(struct work_struct *work)
158181
{
159-
struct {
160-
u8 tag;
161-
u8 len;
162-
u8 ssid[8];
163-
} __packed ssid = {
164-
.tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi",
165-
};
166-
struct cfg80211_bss *informed_bss;
167182
struct virt_wifi_wiphy_priv *priv =
168183
container_of(work, struct virt_wifi_wiphy_priv,
169184
scan_result.work);
170185
struct wiphy *wiphy = priv_to_wiphy(priv);
171186
struct cfg80211_scan_info scan_info = { .aborted = false };
172-
u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);
173187

174-
informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
175-
CFG80211_BSS_FTYPE_PRESP,
176-
fake_router_bssid, tsf,
177-
WLAN_CAPABILITY_ESS, 0,
178-
(void *)&ssid, sizeof(ssid),
179-
DBM_TO_MBM(-50), GFP_KERNEL);
180-
cfg80211_put_bss(wiphy, informed_bss);
188+
virt_wifi_inform_bss(wiphy);
181189

182190
/* Schedules work which acquires and releases the rtnl lock. */
183191
cfg80211_scan_done(priv->scan_request, &scan_info);
@@ -225,10 +233,12 @@ static int virt_wifi_connect(struct wiphy *wiphy, struct net_device *netdev,
225233
if (!could_schedule)
226234
return -EBUSY;
227235

228-
if (sme->bssid)
236+
if (sme->bssid) {
229237
ether_addr_copy(priv->connect_requested_bss, sme->bssid);
230-
else
238+
} else {
239+
virt_wifi_inform_bss(wiphy);
231240
eth_zero_addr(priv->connect_requested_bss);
241+
}
232242

233243
wiphy_debug(wiphy, "connect\n");
234244

@@ -241,11 +251,13 @@ static void virt_wifi_connect_complete(struct work_struct *work)
241251
struct virt_wifi_netdev_priv *priv =
242252
container_of(work, struct virt_wifi_netdev_priv, connect.work);
243253
u8 *requested_bss = priv->connect_requested_bss;
244-
bool has_addr = !is_zero_ether_addr(requested_bss);
245254
bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid);
246255
u16 status = WLAN_STATUS_SUCCESS;
247256

248-
if (!priv->is_up || (has_addr && !right_addr))
257+
if (is_zero_ether_addr(requested_bss))
258+
requested_bss = NULL;
259+
260+
if (!priv->is_up || (requested_bss && !right_addr))
249261
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
250262
else
251263
priv->is_connected = true;

net/mac80211/cfg.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
152152
struct vif_params *params)
153153
{
154154
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
155+
struct ieee80211_local *local = sdata->local;
156+
struct sta_info *sta;
155157
int ret;
156158

157159
ret = ieee80211_if_change_type(sdata, type);
@@ -162,7 +164,24 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
162164
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
163165
ieee80211_check_fast_rx_iface(sdata);
164166
} else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) {
167+
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
168+
169+
if (params->use_4addr == ifmgd->use_4addr)
170+
return 0;
171+
165172
sdata->u.mgd.use_4addr = params->use_4addr;
173+
if (!ifmgd->associated)
174+
return 0;
175+
176+
mutex_lock(&local->sta_mtx);
177+
sta = sta_info_get(sdata, ifmgd->bssid);
178+
if (sta)
179+
drv_sta_set_4addr(local, sdata, &sta->sta,
180+
params->use_4addr);
181+
mutex_unlock(&local->sta_mtx);
182+
183+
if (params->use_4addr)
184+
ieee80211_send_4addr_nullfunc(local, sdata);
166185
}
167186

168187
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {

net/mac80211/ieee80211_i.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,6 +2201,8 @@ void ieee80211_dynamic_ps_timer(struct timer_list *t);
22012201
void ieee80211_send_nullfunc(struct ieee80211_local *local,
22022202
struct ieee80211_sub_if_data *sdata,
22032203
bool powersave);
2204+
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
2205+
struct ieee80211_sub_if_data *sdata);
22042206
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
22052207
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
22062208

net/mac80211/mlme.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,8 +1095,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
10951095
ieee80211_tx_skb(sdata, skb);
10961096
}
10971097

1098-
static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
1099-
struct ieee80211_sub_if_data *sdata)
1098+
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
1099+
struct ieee80211_sub_if_data *sdata)
11001100
{
11011101
struct sk_buff *skb;
11021102
struct ieee80211_hdr *nullfunc;

net/mac80211/rx.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,8 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local,
730730
* Need to make a copy and possibly remove radiotap header
731731
* and FCS from the original.
732732
*/
733-
skb = skb_copy_expand(*origskb, needed_headroom, 0, GFP_ATOMIC);
733+
skb = skb_copy_expand(*origskb, needed_headroom + NET_SKB_PAD,
734+
0, GFP_ATOMIC);
734735

735736
if (!skb)
736737
return NULL;

net/mac80211/tx.c

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,29 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
11471147
return queued;
11481148
}
11491149

1150+
static void
1151+
ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
1152+
struct sta_info *sta,
1153+
struct sk_buff *skb)
1154+
{
1155+
struct rate_control_ref *ref = sdata->local->rate_ctrl;
1156+
u16 tid;
1157+
1158+
if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER))
1159+
return;
1160+
1161+
if (!sta || !sta->sta.ht_cap.ht_supported ||
1162+
!sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO ||
1163+
skb->protocol == sdata->control_port_protocol)
1164+
return;
1165+
1166+
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
1167+
if (likely(sta->ampdu_mlme.tid_tx[tid]))
1168+
return;
1169+
1170+
ieee80211_start_tx_ba_session(&sta->sta, tid, 0);
1171+
}
1172+
11501173
/*
11511174
* initialises @tx
11521175
* 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,
11601183
struct ieee80211_local *local = sdata->local;
11611184
struct ieee80211_hdr *hdr;
11621185
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1186+
bool aggr_check = false;
11631187
int tid;
11641188

11651189
memset(tx, 0, sizeof(*tx));
@@ -1188,8 +1212,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
11881212
} else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
11891213
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
11901214
}
1191-
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
1215+
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) {
11921216
tx->sta = sta_info_get(sdata, hdr->addr1);
1217+
aggr_check = true;
1218+
}
11931219
}
11941220

11951221
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
@@ -1199,8 +1225,12 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
11991225
struct tid_ampdu_tx *tid_tx;
12001226

12011227
tid = ieee80211_get_tid(hdr);
1202-
12031228
tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
1229+
if (!tid_tx && aggr_check) {
1230+
ieee80211_aggr_check(sdata, tx->sta, skb);
1231+
tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
1232+
}
1233+
12041234
if (tid_tx) {
12051235
bool queued;
12061236

@@ -4120,29 +4150,6 @@ void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
41204150
}
41214151
EXPORT_SYMBOL(ieee80211_txq_schedule_start);
41224152

4123-
static void
4124-
ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
4125-
struct sta_info *sta,
4126-
struct sk_buff *skb)
4127-
{
4128-
struct rate_control_ref *ref = sdata->local->rate_ctrl;
4129-
u16 tid;
4130-
4131-
if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER))
4132-
return;
4133-
4134-
if (!sta || !sta->sta.ht_cap.ht_supported ||
4135-
!sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO ||
4136-
skb->protocol == sdata->control_port_protocol)
4137-
return;
4138-
4139-
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
4140-
if (likely(sta->ampdu_mlme.tid_tx[tid]))
4141-
return;
4142-
4143-
ieee80211_start_tx_ba_session(&sta->sta, tid, 0);
4144-
}
4145-
41464153
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
41474154
struct net_device *dev,
41484155
u32 info_flags,

net/wireless/nl80211.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2351,7 +2351,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
23512351
goto nla_put_failure;
23522352

23532353
for (band = state->band_start;
2354-
band < NUM_NL80211_BANDS; band++) {
2354+
band < (state->split ?
2355+
NUM_NL80211_BANDS :
2356+
NL80211_BAND_60GHZ + 1);
2357+
band++) {
23552358
struct ieee80211_supported_band *sband;
23562359

23572360
/* omit higher bands for ancient software */

net/wireless/scan.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,16 +1754,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
17541754
* be grouped with this beacon for updates ...
17551755
*/
17561756
if (!cfg80211_combine_bsses(rdev, new)) {
1757-
kfree(new);
1757+
bss_ref_put(rdev, new);
17581758
goto drop;
17591759
}
17601760
}
17611761

17621762
if (rdev->bss_entries >= bss_entries_limit &&
17631763
!cfg80211_bss_expire_oldest(rdev)) {
1764-
if (!list_empty(&new->hidden_list))
1765-
list_del(&new->hidden_list);
1766-
kfree(new);
1764+
bss_ref_put(rdev, new);
17671765
goto drop;
17681766
}
17691767

0 commit comments

Comments
 (0)