Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nl80211: add scan width to bss and scan request structs

To allow scanning and working with 5 MHz and 10 MHz BSS, extend the
inform bss commands and add wrappers to take 5 and 10 MHz bss into
account.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

authored by

Simon Wunderlich and committed by
Johannes Berg
dcd6eac1 be29b99a

+97 -19
+51 -3
include/net/cfg80211.h
··· 1285 1285 * @n_ssids: number of SSIDs 1286 1286 * @channels: channels to scan on. 1287 1287 * @n_channels: total number of channels to scan 1288 + * @scan_width: channel width for scanning 1288 1289 * @ie: optional information element(s) to add into Probe Request or %NULL 1289 1290 * @ie_len: length of ie in octets 1290 1291 * @flags: bit field of flags controlling operation ··· 1301 1300 struct cfg80211_ssid *ssids; 1302 1301 int n_ssids; 1303 1302 u32 n_channels; 1303 + enum nl80211_bss_scan_width scan_width; 1304 1304 const u8 *ie; 1305 1305 size_t ie_len; 1306 1306 u32 flags; ··· 1335 1333 * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) 1336 1334 * @n_ssids: number of SSIDs 1337 1335 * @n_channels: total number of channels to scan 1336 + * @scan_width: channel width for scanning 1338 1337 * @interval: interval between each scheduled scan cycle 1339 1338 * @ie: optional information element(s) to add into Probe Request or %NULL 1340 1339 * @ie_len: length of ie in octets ··· 1355 1352 struct cfg80211_ssid *ssids; 1356 1353 int n_ssids; 1357 1354 u32 n_channels; 1355 + enum nl80211_bss_scan_width scan_width; 1358 1356 u32 interval; 1359 1357 const u8 *ie; 1360 1358 size_t ie_len; ··· 1407 1403 * for use in scan results and similar. 1408 1404 * 1409 1405 * @channel: channel this BSS is on 1406 + * @scan_width: width of the control channel 1410 1407 * @bssid: BSSID of the BSS 1411 1408 * @beacon_interval: the beacon interval as from the frame 1412 1409 * @capability: the capability field in host byte order ··· 1429 1424 */ 1430 1425 struct cfg80211_bss { 1431 1426 struct ieee80211_channel *channel; 1427 + enum nl80211_bss_scan_width scan_width; 1432 1428 1433 1429 const struct cfg80211_bss_ies __rcu *ies; 1434 1430 const struct cfg80211_bss_ies __rcu *beacon_ies; ··· 3444 3438 void cfg80211_sched_scan_stopped(struct wiphy *wiphy); 3445 3439 3446 3440 /** 3447 - * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame 3441 + * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame 3448 3442 * 3449 3443 * @wiphy: the wiphy reporting the BSS 3450 3444 * @channel: The channel the frame was received on 3445 + * @scan_width: width of the control channel 3451 3446 * @mgmt: the management frame (probe response or beacon) 3452 3447 * @len: length of the management frame 3453 3448 * @signal: the signal strength, type depends on the wiphy's signal_type ··· 3461 3454 * Or %NULL on error. 3462 3455 */ 3463 3456 struct cfg80211_bss * __must_check 3457 + cfg80211_inform_bss_width_frame(struct wiphy *wiphy, 3458 + struct ieee80211_channel *channel, 3459 + enum nl80211_bss_scan_width scan_width, 3460 + struct ieee80211_mgmt *mgmt, size_t len, 3461 + s32 signal, gfp_t gfp); 3462 + 3463 + static inline struct cfg80211_bss * __must_check 3464 3464 cfg80211_inform_bss_frame(struct wiphy *wiphy, 3465 3465 struct ieee80211_channel *channel, 3466 3466 struct ieee80211_mgmt *mgmt, size_t len, 3467 - s32 signal, gfp_t gfp); 3467 + s32 signal, gfp_t gfp) 3468 + { 3469 + return cfg80211_inform_bss_width_frame(wiphy, channel, 3470 + NL80211_BSS_CHAN_WIDTH_20, 3471 + mgmt, len, signal, gfp); 3472 + } 3468 3473 3469 3474 /** 3470 3475 * cfg80211_inform_bss - inform cfg80211 of a new BSS 3471 3476 * 3472 3477 * @wiphy: the wiphy reporting the BSS 3473 3478 * @channel: The channel the frame was received on 3479 + * @scan_width: width of the control channel 3474 3480 * @bssid: the BSSID of the BSS 3475 3481 * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) 3476 3482 * @capability: the capability field sent by the peer ··· 3500 3480 * Or %NULL on error. 3501 3481 */ 3502 3482 struct cfg80211_bss * __must_check 3483 + cfg80211_inform_bss_width(struct wiphy *wiphy, 3484 + struct ieee80211_channel *channel, 3485 + enum nl80211_bss_scan_width scan_width, 3486 + const u8 *bssid, u64 tsf, u16 capability, 3487 + u16 beacon_interval, const u8 *ie, size_t ielen, 3488 + s32 signal, gfp_t gfp); 3489 + 3490 + static inline struct cfg80211_bss * __must_check 3503 3491 cfg80211_inform_bss(struct wiphy *wiphy, 3504 3492 struct ieee80211_channel *channel, 3505 3493 const u8 *bssid, u64 tsf, u16 capability, 3506 3494 u16 beacon_interval, const u8 *ie, size_t ielen, 3507 - s32 signal, gfp_t gfp); 3495 + s32 signal, gfp_t gfp) 3496 + { 3497 + return cfg80211_inform_bss_width(wiphy, channel, 3498 + NL80211_BSS_CHAN_WIDTH_20, 3499 + bssid, tsf, capability, 3500 + beacon_interval, ie, ielen, signal, 3501 + gfp); 3502 + } 3508 3503 3509 3504 struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, 3510 3505 struct ieee80211_channel *channel, ··· 3564 3529 * out, so it is not necessary to use this function at all. 3565 3530 */ 3566 3531 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); 3532 + 3533 + static inline enum nl80211_bss_scan_width 3534 + cfg80211_chandef_to_scan_width(const struct cfg80211_chan_def *chandef) 3535 + { 3536 + switch (chandef->width) { 3537 + case NL80211_CHAN_WIDTH_5: 3538 + return NL80211_BSS_CHAN_WIDTH_5; 3539 + case NL80211_CHAN_WIDTH_10: 3540 + return NL80211_BSS_CHAN_WIDTH_10; 3541 + default: 3542 + return NL80211_BSS_CHAN_WIDTH_20; 3543 + } 3544 + } 3567 3545 3568 3546 /** 3569 3547 * cfg80211_rx_mlme_mgmt - notification of processed MLME management frame
+18
include/uapi/linux/nl80211.h
··· 2808 2808 }; 2809 2809 2810 2810 /** 2811 + * enum nl80211_bss_scan_width - control channel width for a BSS 2812 + * 2813 + * These values are used with the %NL80211_BSS_CHAN_WIDTH attribute. 2814 + * 2815 + * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible 2816 + * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide 2817 + * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide 2818 + */ 2819 + enum nl80211_bss_scan_width { 2820 + NL80211_BSS_CHAN_WIDTH_20, 2821 + NL80211_BSS_CHAN_WIDTH_10, 2822 + NL80211_BSS_CHAN_WIDTH_5, 2823 + }; 2824 + 2825 + /** 2811 2826 * enum nl80211_bss - netlink attributes for a BSS 2812 2827 * 2813 2828 * @__NL80211_BSS_INVALID: invalid ··· 2846 2831 * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information 2847 2832 * elements from a Beacon frame (bin); not present if no Beacon frame has 2848 2833 * yet been received 2834 + * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel 2835 + * (u32, enum nl80211_bss_scan_width) 2849 2836 * @__NL80211_BSS_AFTER_LAST: internal 2850 2837 * @NL80211_BSS_MAX: highest BSS attribute 2851 2838 */ ··· 2864 2847 NL80211_BSS_STATUS, 2865 2848 NL80211_BSS_SEEN_MS_AGO, 2866 2849 NL80211_BSS_BEACON_IES, 2850 + NL80211_BSS_CHAN_WIDTH, 2867 2851 2868 2852 /* keep last */ 2869 2853 __NL80211_BSS_AFTER_LAST,
+1
net/wireless/nl80211.c
··· 5674 5674 goto nla_put_failure; 5675 5675 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) || 5676 5676 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) || 5677 + nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) || 5677 5678 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO, 5678 5679 jiffies_to_msecs(jiffies - intbss->ts))) 5679 5680 goto nla_put_failure;
+19 -12
net/wireless/scan.c
··· 651 651 continue; 652 652 if (bss->pub.channel != new->pub.channel) 653 653 continue; 654 + if (bss->pub.scan_width != new->pub.scan_width) 655 + continue; 654 656 if (rcu_access_pointer(bss->pub.beacon_ies)) 655 657 continue; 656 658 ies = rcu_access_pointer(bss->pub.ies); ··· 872 870 873 871 /* Returned bss is reference counted and must be cleaned up appropriately. */ 874 872 struct cfg80211_bss* 875 - cfg80211_inform_bss(struct wiphy *wiphy, 876 - struct ieee80211_channel *channel, 877 - const u8 *bssid, u64 tsf, u16 capability, 878 - u16 beacon_interval, const u8 *ie, size_t ielen, 879 - s32 signal, gfp_t gfp) 873 + cfg80211_inform_bss_width(struct wiphy *wiphy, 874 + struct ieee80211_channel *channel, 875 + enum nl80211_bss_scan_width scan_width, 876 + const u8 *bssid, u64 tsf, u16 capability, 877 + u16 beacon_interval, const u8 *ie, size_t ielen, 878 + s32 signal, gfp_t gfp) 880 879 { 881 880 struct cfg80211_bss_ies *ies; 882 881 struct cfg80211_internal_bss tmp = {}, *res; ··· 895 892 896 893 memcpy(tmp.pub.bssid, bssid, ETH_ALEN); 897 894 tmp.pub.channel = channel; 895 + tmp.pub.scan_width = scan_width; 898 896 tmp.pub.signal = signal; 899 897 tmp.pub.beacon_interval = beacon_interval; 900 898 tmp.pub.capability = capability; ··· 928 924 /* cfg80211_bss_update gives us a referenced result */ 929 925 return &res->pub; 930 926 } 931 - EXPORT_SYMBOL(cfg80211_inform_bss); 927 + EXPORT_SYMBOL(cfg80211_inform_bss_width); 932 928 933 929 /* Returned bss is reference counted and must be cleaned up appropriately. */ 934 930 struct cfg80211_bss * 935 - cfg80211_inform_bss_frame(struct wiphy *wiphy, 936 - struct ieee80211_channel *channel, 937 - struct ieee80211_mgmt *mgmt, size_t len, 938 - s32 signal, gfp_t gfp) 931 + cfg80211_inform_bss_width_frame(struct wiphy *wiphy, 932 + struct ieee80211_channel *channel, 933 + enum nl80211_bss_scan_width scan_width, 934 + struct ieee80211_mgmt *mgmt, size_t len, 935 + s32 signal, gfp_t gfp) 939 936 { 940 937 struct cfg80211_internal_bss tmp = {}, *res; 941 938 struct cfg80211_bss_ies *ies; ··· 946 941 BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != 947 942 offsetof(struct ieee80211_mgmt, u.beacon.variable)); 948 943 949 - trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal); 944 + trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt, 945 + len, signal); 950 946 951 947 if (WARN_ON(!mgmt)) 952 948 return NULL; ··· 982 976 983 977 memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); 984 978 tmp.pub.channel = channel; 979 + tmp.pub.scan_width = scan_width; 985 980 tmp.pub.signal = signal; 986 981 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 987 982 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ··· 998 991 /* cfg80211_bss_update gives us a referenced result */ 999 992 return &res->pub; 1000 993 } 1001 - EXPORT_SYMBOL(cfg80211_inform_bss_frame); 994 + EXPORT_SYMBOL(cfg80211_inform_bss_width_frame); 1002 995 1003 996 void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) 1004 997 {
+8 -4
net/wireless/trace.h
··· 2391 2391 __entry->capa_mask, __entry->capa_val) 2392 2392 ); 2393 2393 2394 - TRACE_EVENT(cfg80211_inform_bss_frame, 2394 + TRACE_EVENT(cfg80211_inform_bss_width_frame, 2395 2395 TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, 2396 + enum nl80211_bss_scan_width scan_width, 2396 2397 struct ieee80211_mgmt *mgmt, size_t len, 2397 2398 s32 signal), 2398 - TP_ARGS(wiphy, channel, mgmt, len, signal), 2399 + TP_ARGS(wiphy, channel, scan_width, mgmt, len, signal), 2399 2400 TP_STRUCT__entry( 2400 2401 WIPHY_ENTRY 2401 2402 CHAN_ENTRY 2403 + __field(enum nl80211_bss_scan_width, scan_width) 2402 2404 __dynamic_array(u8, mgmt, len) 2403 2405 __field(s32, signal) 2404 2406 ), 2405 2407 TP_fast_assign( 2406 2408 WIPHY_ASSIGN; 2407 2409 CHAN_ASSIGN(channel); 2410 + __entry->scan_width = scan_width; 2408 2411 if (mgmt) 2409 2412 memcpy(__get_dynamic_array(mgmt), mgmt, len); 2410 2413 __entry->signal = signal; 2411 2414 ), 2412 - TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d", 2413 - WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal) 2415 + TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d", 2416 + WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, 2417 + __entry->signal) 2414 2418 ); 2415 2419 2416 2420 DECLARE_EVENT_CLASS(cfg80211_bss_evt,