Skip to content

Commit 5f3b9d3

Browse files
committed
Merge tag 'mac80211-next-for-davem-2016-08-12' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== Not much for -next so far, but here it goes: * send more nl80211 events for interfaces * remove useless network/transport offset mangling code * validate beacon intervals identically for all interface types * use driver rate estimates for mesh * fix a compiler type/signedness warning ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 7056783 + ff9a71a commit 5f3b9d3

File tree

9 files changed

+112
-83
lines changed

9 files changed

+112
-83
lines changed

net/mac80211/driver-ops.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,13 +1088,13 @@ static inline void drv_leave_ibss(struct ieee80211_local *local,
10881088
}
10891089

10901090
static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
1091-
struct ieee80211_sta *sta)
1091+
struct sta_info *sta)
10921092
{
10931093
u32 ret = 0;
10941094

1095-
trace_drv_get_expected_throughput(sta);
1096-
if (local->ops->get_expected_throughput)
1097-
ret = local->ops->get_expected_throughput(&local->hw, sta);
1095+
trace_drv_get_expected_throughput(&sta->sta);
1096+
if (local->ops->get_expected_throughput && sta->uploaded)
1097+
ret = local->ops->get_expected_throughput(&local->hw, &sta->sta);
10981098
trace_drv_return_u32(local, ret);
10991099

11001100
return ret;

net/mac80211/mesh_hwmp.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,22 +326,33 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
326326
u32 tx_time, estimated_retx;
327327
u64 result;
328328

329-
if (sta->mesh->fail_avg >= 100)
330-
return MAX_METRIC;
329+
/* Try to get rate based on HW/SW RC algorithm.
330+
* Rate is returned in units of Kbps, correct this
331+
* to comply with airtime calculation units
332+
* Round up in case we get rate < 100Kbps
333+
*/
334+
rate = DIV_ROUND_UP(sta_get_expected_throughput(sta), 100);
331335

332-
sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
333-
rate = cfg80211_calculate_bitrate(&rinfo);
334-
if (WARN_ON(!rate))
335-
return MAX_METRIC;
336+
if (rate) {
337+
err = 0;
338+
} else {
339+
if (sta->mesh->fail_avg >= 100)
340+
return MAX_METRIC;
336341

337-
err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
342+
sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
343+
rate = cfg80211_calculate_bitrate(&rinfo);
344+
if (WARN_ON(!rate))
345+
return MAX_METRIC;
346+
347+
err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
348+
}
338349

339350
/* bitrate is in units of 100 Kbps, while we need rate in units of
340351
* 1Mbps. This will be corrected on tx_time computation.
341352
*/
342353
tx_time = (device_constant + 10 * test_frame_len / rate);
343354
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
344-
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
355+
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
345356
return (u32)result;
346357
}
347358

net/mac80211/sta_info.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,18 +2279,33 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
22792279
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
22802280
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
22812281

2282-
/* check if the driver has a SW RC implementation */
2283-
if (ref && ref->ops->get_expected_throughput)
2284-
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
2285-
else
2286-
thr = drv_get_expected_throughput(local, &sta->sta);
2282+
thr = sta_get_expected_throughput(sta);
22872283

22882284
if (thr != 0) {
22892285
sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
22902286
sinfo->expected_throughput = thr;
22912287
}
22922288
}
22932289

2290+
u32 sta_get_expected_throughput(struct sta_info *sta)
2291+
{
2292+
struct ieee80211_sub_if_data *sdata = sta->sdata;
2293+
struct ieee80211_local *local = sdata->local;
2294+
struct rate_control_ref *ref = NULL;
2295+
u32 thr = 0;
2296+
2297+
if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
2298+
ref = local->rate_ctrl;
2299+
2300+
/* check if the driver has a SW RC implementation */
2301+
if (ref && ref->ops->get_expected_throughput)
2302+
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
2303+
else
2304+
thr = drv_get_expected_throughput(local, sta);
2305+
2306+
return thr;
2307+
}
2308+
22942309
unsigned long ieee80211_sta_last_active(struct sta_info *sta)
22952310
{
22962311
struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);

net/mac80211/sta_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
712712
struct rate_info *rinfo);
713713
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
714714

715+
u32 sta_get_expected_throughput(struct sta_info *sta);
716+
715717
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
716718
unsigned long exp_time);
717719
u8 sta_info_tx_streams(struct sta_info *sta);

net/mac80211/tx.c

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2334,7 +2334,6 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
23342334
struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;
23352335
const u8 *encaps_data;
23362336
int encaps_len, skip_header_bytes;
2337-
int nh_pos, h_pos;
23382337
bool wme_sta = false, authorized = false;
23392338
bool tdls_peer;
23402339
bool multicast;
@@ -2640,13 +2639,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
26402639
encaps_len = 0;
26412640
}
26422641

2643-
nh_pos = skb_network_header(skb) - skb->data;
2644-
h_pos = skb_transport_header(skb) - skb->data;
2645-
26462642
skb_pull(skb, skip_header_bytes);
2647-
nh_pos -= skip_header_bytes;
2648-
h_pos -= skip_header_bytes;
2649-
26502643
head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
26512644

26522645
/*
@@ -2672,18 +2665,12 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
26722665
}
26732666
}
26742667

2675-
if (encaps_data) {
2668+
if (encaps_data)
26762669
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
2677-
nh_pos += encaps_len;
2678-
h_pos += encaps_len;
2679-
}
26802670

26812671
#ifdef CONFIG_MAC80211_MESH
2682-
if (meshhdrlen > 0) {
2672+
if (meshhdrlen > 0)
26832673
memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
2684-
nh_pos += meshhdrlen;
2685-
h_pos += meshhdrlen;
2686-
}
26872674
#endif
26882675

26892676
if (ieee80211_is_data_qos(fc)) {
@@ -2699,15 +2686,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
26992686
} else
27002687
memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
27012688

2702-
nh_pos += hdrlen;
2703-
h_pos += hdrlen;
2704-
2705-
/* Update skb pointers to various headers since this modified frame
2706-
* is going to go through Linux networking code that may potentially
2707-
* need things like pointer to IP header. */
27082689
skb_reset_mac_header(skb);
2709-
skb_set_network_header(skb, nh_pos);
2710-
skb_set_transport_header(skb, h_pos);
27112690

27122691
info = IEEE80211_SKB_CB(skb);
27132692
memset(info, 0, sizeof(*info));
@@ -4390,9 +4369,6 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
43904369
int ac = ieee802_1d_to_ac[tid & 7];
43914370

43924371
skb_reset_mac_header(skb);
4393-
skb_reset_network_header(skb);
4394-
skb_reset_transport_header(skb);
4395-
43964372
skb_set_queue_mapping(skb, ac);
43974373
skb->priority = tid;
43984374

net/wireless/core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,8 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
906906
if (WARN_ON(wdev->netdev))
907907
return;
908908

909+
nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
910+
909911
list_del_rcu(&wdev->list);
910912
rdev->devlist_generation++;
911913

@@ -1079,6 +1081,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
10791081
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
10801082
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
10811083
dev->priv_flags |= IFF_DONT_BRIDGE;
1084+
1085+
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
10821086
break;
10831087
case NETDEV_GOING_DOWN:
10841088
cfg80211_leave(rdev, wdev);
@@ -1157,6 +1161,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
11571161
* remove and clean it up.
11581162
*/
11591163
if (!list_empty(&wdev->list)) {
1164+
nl80211_notify_iface(rdev, wdev,
1165+
NL80211_CMD_DEL_INTERFACE);
11601166
sysfs_remove_link(&dev->dev.kobj, "phy80211");
11611167
list_del_rcu(&wdev->list);
11621168
rdev->devlist_generation++;

net/wireless/nl80211.c

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,7 +2751,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
27512751
struct cfg80211_registered_device *rdev = info->user_ptr[0];
27522752
struct vif_params params;
27532753
struct wireless_dev *wdev;
2754-
struct sk_buff *msg, *event;
2754+
struct sk_buff *msg;
27552755
int err;
27562756
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
27572757
u32 flags;
@@ -2855,39 +2855,26 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
28552855
return -ENOBUFS;
28562856
}
28572857

2858-
event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2859-
if (event) {
2860-
if (nl80211_send_iface(event, 0, 0, 0,
2861-
rdev, wdev, false) < 0) {
2862-
nlmsg_free(event);
2863-
goto out;
2864-
}
2865-
2866-
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
2867-
event, 0, NL80211_MCGRP_CONFIG,
2868-
GFP_KERNEL);
2869-
}
2858+
/*
2859+
* For wdevs which have no associated netdev object (e.g. of type
2860+
* NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.
2861+
* For all other types, the event will be generated from the
2862+
* netdev notifier
2863+
*/
2864+
if (!wdev->netdev)
2865+
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
28702866

2871-
out:
28722867
return genlmsg_reply(msg, info);
28732868
}
28742869

28752870
static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
28762871
{
28772872
struct cfg80211_registered_device *rdev = info->user_ptr[0];
28782873
struct wireless_dev *wdev = info->user_ptr[1];
2879-
struct sk_buff *msg;
2880-
int status;
28812874

28822875
if (!rdev->ops->del_virtual_intf)
28832876
return -EOPNOTSUPP;
28842877

2885-
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2886-
if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) {
2887-
nlmsg_free(msg);
2888-
msg = NULL;
2889-
}
2890-
28912878
/*
28922879
* If we remove a wireless device without a netdev then clear
28932880
* user_ptr[1] so that nl80211_post_doit won't dereference it
@@ -2898,15 +2885,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
28982885
if (!wdev->netdev)
28992886
info->user_ptr[1] = NULL;
29002887

2901-
status = rdev_del_virtual_intf(rdev, wdev);
2902-
if (status >= 0 && msg)
2903-
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
2904-
msg, 0, NL80211_MCGRP_CONFIG,
2905-
GFP_KERNEL);
2906-
else
2907-
nlmsg_free(msg);
2908-
2909-
return status;
2888+
return rdev_del_virtual_intf(rdev, wdev);
29102889
}
29112890

29122891
static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -5374,6 +5353,18 @@ static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *ou
53745353
return 0;
53755354
}
53765355

5356+
static int nl80211_check_power_mode(const struct nlattr *nla,
5357+
enum nl80211_mesh_power_mode min,
5358+
enum nl80211_mesh_power_mode max,
5359+
enum nl80211_mesh_power_mode *out)
5360+
{
5361+
u32 val = nla_get_u32(nla);
5362+
if (val < min || val > max)
5363+
return -EINVAL;
5364+
*out = val;
5365+
return 0;
5366+
}
5367+
53775368
static int nl80211_parse_mesh_config(struct genl_info *info,
53785369
struct mesh_config *cfg,
53795370
u32 *mask_out)
@@ -5518,7 +5509,7 @@ do { \
55185509
NL80211_MESH_POWER_ACTIVE,
55195510
NL80211_MESH_POWER_MAX,
55205511
mask, NL80211_MESHCONF_POWER_MODE,
5521-
nl80211_check_u32);
5512+
nl80211_check_power_mode);
55225513
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
55235514
0, 65535, mask,
55245515
NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
@@ -7773,12 +7764,13 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
77737764

77747765
ibss.beacon_interval = 100;
77757766

7776-
if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
7767+
if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
77777768
ibss.beacon_interval =
77787769
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
7779-
if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
7780-
return -EINVAL;
7781-
}
7770+
7771+
err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
7772+
if (err)
7773+
return err;
77827774

77837775
if (!rdev->ops->join_ibss)
77847776
return -EOPNOTSUPP;
@@ -9252,9 +9244,10 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
92529244
if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
92539245
setup.beacon_interval =
92549246
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
9255-
if (setup.beacon_interval < 10 ||
9256-
setup.beacon_interval > 10000)
9257-
return -EINVAL;
9247+
9248+
err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
9249+
if (err)
9250+
return err;
92589251
}
92599252

92609253
if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
@@ -11847,6 +11840,29 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
1184711840
NL80211_MCGRP_CONFIG, GFP_KERNEL);
1184811841
}
1184911842

11843+
void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
11844+
struct wireless_dev *wdev,
11845+
enum nl80211_commands cmd)
11846+
{
11847+
struct sk_buff *msg;
11848+
11849+
WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
11850+
cmd != NL80211_CMD_DEL_INTERFACE);
11851+
11852+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11853+
if (!msg)
11854+
return;
11855+
11856+
if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev,
11857+
cmd == NL80211_CMD_DEL_INTERFACE) < 0) {
11858+
nlmsg_free(msg);
11859+
return;
11860+
}
11861+
11862+
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11863+
NL80211_MCGRP_CONFIG, GFP_KERNEL);
11864+
}
11865+
1185011866
static int nl80211_add_scan_req(struct sk_buff *msg,
1185111867
struct cfg80211_registered_device *rdev)
1185211868
{

net/wireless/nl80211.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ int nl80211_init(void);
77
void nl80211_exit(void);
88
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
99
enum nl80211_commands cmd);
10+
void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
11+
struct wireless_dev *wdev,
12+
enum nl80211_commands cmd);
1013
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
1114
struct wireless_dev *wdev);
1215
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,

net/wireless/util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
15591559
struct wireless_dev *wdev;
15601560
int res = 0;
15611561

1562-
if (!beacon_int)
1562+
if (beacon_int < 10 || beacon_int > 10000)
15631563
return -EINVAL;
15641564

15651565
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {

0 commit comments

Comments
 (0)