A couple of weeks worth of updates - looks like things are quiet:

* merged net-next back to get a patch from net that another patch
    here depends on
  * various small improvements/cleanups across the board
  * 4-way handshake offload (many thanks to Arend for shepherding that)
  * mesh CSA/DFS support in mac80211
  * the skb_put_zero() we discussed previously
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEExu3sM/nZ1eRSfR9Ha3t4Rpy0AB0FAlk/2HoACgkQa3t4Rpy0
 AB3psA/8CVT+cJHH6fQoP2ev17LMB5CF/bBaRh8jeYRg/RslofwptLaG6CVi/Eri
 RSf036q1pUqpS7BlBguCUwqtNGIKvhr3AUIuN0nQsrH4iPJMl8DaCHM4a7BigdtG
 Cq4N7GTS5gJcUcjpxcOIoCsrpdkp8Lvnz6z7nBIxemYAyGuxrW2Z9ES38fh4TTlS
 k+8h+c8+K0Q3WsT5BB3i7zTTBLLhpR9r1YcbNf4Y984vF/Blc4M1ggbWMPZZG/y8
 CdOMH3dM9FHrzyHeyRC2ppVah6GBUgeccSlJP5KcF2vsMi2fVRwfxWTFXaQzgJy7
 lS2bKuqAiLopaYAmq/fSMBygxm2GPSsKtc2lz+TLXXTL18fqpIq7ZTjZLE+gYTCv
 DB0GamoaFciEKJ+jOvy95y2WRMnYia2whBrzsUzQ4Uful6vXbr5Q5ue5xCj4t4Qe
 bbveAdVl7n7m1pqtq9A3YP0m/lX2f7BIv2DF5bM1XoHohZHDdvETDF7NE2BIsT/I
 QFem5ffcBQRZPmdg7Tkh3K79tA4JA/ML4cx8W7Te9k+aOtaFR+ojA4pnH/8fI9d/
 6hIPuLwxI+OWGYNglxyIbuzZ4KiQr5JnZe4OFk4+/Y2g01ALY3DAbXnCVIXJIh8e
 bqUf+1Bai6EnxLDWx4qehB+bPVHzHYmvlZeJud+KJPUU/NZ9YSw=
 =x2vs
 -----END PGP SIGNATURE-----

Merge tag 'mac80211-next-for-davem-2017-06-13' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
A couple of weeks worth of updates - looks like things are quiet:
 * merged net-next back to get a patch from net that another patch
   here depends on
 * various small improvements/cleanups across the board
 * 4-way handshake offload (many thanks to Arend for shepherding that)
 * mesh CSA/DFS support in mac80211
 * the skb_put_zero() we discussed previously
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2017-06-13 13:52:37 -04:00
commit 0e74008b66
32 changed files with 620 additions and 111 deletions

View File

@ -2400,7 +2400,11 @@ enum ieee80211_sa_query_action {
#define WLAN_MAX_KEY_LEN 32
#define WLAN_PMK_NAME_LEN 16
#define WLAN_PMKID_LEN 16
#define WLAN_PMK_LEN_EAP_LEAP 16
#define WLAN_PMK_LEN 32
#define WLAN_PMK_LEN_SUITE_B_192 48
#define WLAN_OUI_WFA 0x506f9a
#define WLAN_OUI_TYPE_WFA_P2P 9

View File

@ -1904,6 +1904,15 @@ static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
return tmp;
}
static inline unsigned char *skb_put_zero(struct sk_buff *skb, unsigned int len)
{
unsigned char *tmp = skb_put(skb, len);
memset(tmp, 0, len);
return tmp;
}
unsigned char *skb_push(struct sk_buff *skb, unsigned int len);
static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
{

View File

@ -649,6 +649,7 @@ struct survey_info {
* @wep_keys: static WEP keys, if not NULL points to an array of
* CFG80211_MAX_WEP_KEYS WEP keys
* @wep_tx_key: key index (0..3) of the default TX static WEP key
* @psk: PSK (for devices supporting 4-way-handshake offload)
*/
struct cfg80211_crypto_settings {
u32 wpa_versions;
@ -662,6 +663,7 @@ struct cfg80211_crypto_settings {
bool control_port_no_encrypt;
struct key_params *wep_keys;
int wep_tx_key;
const u8 *psk;
};
/**
@ -1441,6 +1443,9 @@ struct mesh_config {
* @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
* @basic_rates: basic rates to use when creating the mesh
* @beacon_rate: bitrate to be used for beacons
* @userspace_handles_dfs: whether user space controls DFS operation, i.e.
* changes the channel when a radar is detected. This is required
* to operate on DFS channels.
*
* These parameters are fixed when the mesh is created.
*/
@ -1462,6 +1467,7 @@ struct mesh_setup {
int mcast_rate[NUM_NL80211_BANDS];
u32 basic_rates;
struct cfg80211_bitrate_mask beacon_rate;
bool userspace_handles_dfs;
};
/**
@ -2106,6 +2112,8 @@ struct cfg80211_bss_selection {
* @fils_erp_rrk: ERP re-authentication Root Key (rRK) used to derive additional
* keys in FILS or %NULL if not specified.
* @fils_erp_rrk_len: Length of @fils_erp_rrk in octets.
* @want_1x: indicates user-space supports and wants to use 802.1X driver
* offload of 4-way handshake.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
@ -2138,6 +2146,7 @@ struct cfg80211_connect_params {
u16 fils_erp_next_seq_num;
const u8 *fils_erp_rrk;
size_t fils_erp_rrk_len;
bool want_1x;
};
/**
@ -2559,6 +2568,23 @@ struct cfg80211_nan_func {
u64 cookie;
};
/**
* struct cfg80211_pmk_conf - PMK configuration
*
* @aa: authenticator address
* @pmk_len: PMK length in bytes.
* @pmk: the PMK material
* @pmk_r0_name: PMK-R0 Name. NULL if not applicable (i.e., the PMK
* is not PMK-R0). When pmk_r0_name is not NULL, the pmk field
* holds PMK-R0.
*/
struct cfg80211_pmk_conf {
const u8 *aa;
u8 pmk_len;
const u8 *pmk;
const u8 *pmk_r0_name;
};
/**
* struct cfg80211_ops - backend description for wireless configuration
*
@ -2875,6 +2901,13 @@ struct cfg80211_nan_func {
* All other parameters must be ignored.
*
* @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
*
* @set_pmk: configure the PMK to be used for offloaded 802.1X 4-Way handshake.
* If not deleted through @del_pmk the PMK remains valid until disconnect
* upon which the driver should clear it.
* (invoked with the wireless_dev mutex held)
* @del_pmk: delete the previously configured PMK for the given authenticator.
* (invoked with the wireless_dev mutex held)
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@ -3163,6 +3196,11 @@ struct cfg80211_ops {
int (*set_multicast_to_unicast)(struct wiphy *wiphy,
struct net_device *dev,
const bool enabled);
int (*set_pmk)(struct wiphy *wiphy, struct net_device *dev,
const struct cfg80211_pmk_conf *conf);
int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
const u8 *aa);
};
/*
@ -5403,6 +5441,9 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
* @req_ie_len: association request IEs length
* @resp_ie: association response IEs (may be %NULL)
* @resp_ie_len: assoc response IEs length
* @authorized: true if the 802.1X authentication was done by the driver or is
* not needed (e.g., when Fast Transition protocol was used), false
* otherwise. Ignored for networks that don't use 802.1X authentication.
*/
struct cfg80211_roam_info {
struct ieee80211_channel *channel;
@ -5412,6 +5453,7 @@ struct cfg80211_roam_info {
size_t req_ie_len;
const u8 *resp_ie;
size_t resp_ie_len;
bool authorized;
};
/**

View File

@ -4204,6 +4204,22 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
struct ieee80211_tx_rate *dest,
int max_rates);
/**
* ieee80211_sta_set_expected_throughput - set the expected tpt for a station
*
* Call this function to notify mac80211 about a change in expected throughput
* to a station. A driver for a device that does rate control in firmware can
* call this function when the expected throughput estimate towards a station
* changes. The information is used to tune the CoDel AQM applied to traffic
* going towards that station (which can otherwise be too aggressive and cause
* slow stations to starve).
*
* @pubsta: the station to set throughput for.
* @thr: the current expected throughput in kbps.
*/
void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
u32 thr);
/**
* ieee80211_tx_status - transmit status callback
*
@ -5436,6 +5452,9 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
*/
void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr,
unsigned int bit);
/**
* ieee80211_start_rx_ba_session_offl - start a Rx BA session
*
@ -5450,8 +5469,13 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
* @addr: station mac address
* @tid: the rx tid
*/
void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
const u8 *addr, u16 tid);
static inline void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
const u8 *addr, u16 tid)
{
if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
return;
ieee80211_manage_rx_ba_offl(vif, addr, tid);
}
/**
* ieee80211_stop_rx_ba_session_offl - stop a Rx BA session
@ -5467,8 +5491,13 @@ void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
* @addr: station mac address
* @tid: the rx tid
*/
void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
const u8 *addr, u16 tid);
static inline void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
const u8 *addr, u16 tid)
{
if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
return;
ieee80211_manage_rx_ba_offl(vif, addr, tid + IEEE80211_NUM_TIDS);
}
/* Rate control API */

View File

@ -172,6 +172,29 @@
* Multiple such rules can be created.
*/
/**
* DOC: WPA/WPA2 EAPOL handshake offload
*
* By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag drivers
* can indicate they support offloading EAPOL handshakes for WPA/WPA2
* preshared key authentication. In %NL80211_CMD_CONNECT the preshared
* key should be specified using %NL80211_ATTR_PMK. Drivers supporting
* this offload may reject the %NL80211_CMD_CONNECT when no preshared
* key material is provided, for example when that driver does not
* support setting the temporal keys through %CMD_NEW_KEY.
*
* Similarly @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X flag can be
* set by drivers indicating offload support of the PTK/GTK EAPOL
* handshakes during 802.1X authentication. In order to use the offload
* the %NL80211_CMD_CONNECT should have %NL80211_ATTR_WANT_1X_4WAY_HS
* attribute flag. Drivers supporting this offload may reject the
* %NL80211_CMD_CONNECT when the attribute flag is not present.
*
* For 802.1X the PMK or PMK-R0 are set by providing %NL80211_ATTR_PMK
* using %NL80211_CMD_SET_PMK. For offloaded FT support also
* %NL80211_ATTR_PMKR0_NAME must be provided.
*/
/**
* DOC: FILS shared key authentication offload
*
@ -546,8 +569,13 @@
* authentication/association or not receiving a response from the AP.
* Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
* well to remain backwards compatible.
* @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
* sent as an event when the card/driver roamed by itself.
* @NL80211_CMD_ROAM: notifcation indicating the card/driver roamed by itself.
* When the driver roamed in a network that requires 802.1X authentication,
* %NL80211_ATTR_PORT_AUTHORIZED should be set if the 802.1X authentication
* was done by the driver or if roaming was done using Fast Transition
* protocol (in which case 802.1X authentication is not needed). If
* %NL80211_ATTR_PORT_AUTHORIZED is not set, user space is responsible for
* the 802.1X authentication.
* @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
* userspace that a connection was dropped by the AP or due to other
* reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
@ -947,6 +975,14 @@
* does not result in a change for the current association. Currently,
* only the %NL80211_ATTR_IE data is used and updated with this command.
*
* @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0
* for the given authenticator address (specified with &NL80211_ATTR_MAC).
* When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the
* PMK-R0, otherwise it specifies the PMK.
* @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
* configured PMK for the authenticator address identified by
* &NL80211_ATTR_MAC.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@ -1146,6 +1182,9 @@ enum nl80211_commands {
NL80211_CMD_UPDATE_CONNECT_PARAMS,
NL80211_CMD_SET_PMK,
NL80211_CMD_DEL_PMK,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@ -2080,14 +2119,27 @@ enum nl80211_commands {
* identifying the scope of PMKSAs. This is used with
* @NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA.
*
* @NL80211_ATTR_PMK: PMK for the PMKSA identified by %NL80211_ATTR_PMKID.
* This is used with @NL80211_CMD_SET_PMKSA.
* @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with
* %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID.
* For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way
* handshake for WPA/WPA2-PSK networks. For 802.1X authentication it is
* used with %NL80211_CMD_SET_PMK. For offloaded FT support this attribute
* specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME is included as well.
*
* @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to
* indicate that it supports multiple active scheduled scan requests.
* @NL80211_ATTR_SCHED_SCAN_MAX_REQS: indicates maximum number of scheduled
* scan request that may be active for the device (u32).
*
* @NL80211_ATTR_WANT_1X_4WAY_HS: flag attribute which user-space can include
* in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it
* wants to use the supported offload of the 4-way handshake.
* @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
* @NL80211_ATTR_PORT_AUTHORIZED: flag attribute used in %NL80211_CMD_ROAMED
* notification indicating that that 802.1X authentication was done by
* the driver or is not needed (because roaming used the Fast Transition
* protocol).
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@ -2510,6 +2562,10 @@ enum nl80211_attrs {
NL80211_ATTR_SCHED_SCAN_MULTI,
NL80211_ATTR_SCHED_SCAN_MAX_REQS,
NL80211_ATTR_WANT_1X_4WAY_HS,
NL80211_ATTR_PMKR0_NAME,
NL80211_ATTR_PORT_AUTHORIZED,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@ -4852,6 +4908,13 @@ enum nl80211_feature_flags {
* RSSI threshold values to monitor rather than exactly one threshold.
* @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD: Driver SME supports FILS shared key
* authentication with %NL80211_CMD_CONNECT.
* @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device wants to do 4-way
* handshake with PSK in station mode (PSK is passed as part of the connect
* and associate commands), doing it in the host might not be supported.
* @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X: Device wants to do doing 4-way
* handshake with 802.1X in station mode (will pass EAP frames to the host
* and accept the set_pmk/del_pmk commands), doing it in the host might not
* be supported.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@ -4872,6 +4935,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
NL80211_EXT_FEATURE_CQM_RSSI_LIST,
NL80211_EXT_FEATURE_FILS_SK_OFFLOAD,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,

View File

@ -449,44 +449,21 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
buf_size, true, false);
}
void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
const u8 *addr, u16 tid)
void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
const u8 *addr, unsigned int bit)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_rx_agg *rx_agg;
struct sk_buff *skb = dev_alloc_skb(0);
struct sta_info *sta;
if (unlikely(!skb))
return;
rcu_read_lock();
sta = sta_info_get_bss(sdata, addr);
if (!sta)
goto unlock;
rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
memcpy(&rx_agg->addr, addr, ETH_ALEN);
rx_agg->tid = tid;
skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &sdata->work);
set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl);
ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
unlock:
rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);
void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
const u8 *addr, u16 tid)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_rx_agg *rx_agg;
struct sk_buff *skb = dev_alloc_skb(0);
if (unlikely(!skb))
return;
rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
memcpy(&rx_agg->addr, addr, ETH_ALEN);
rx_agg->tid = tid;
skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &sdata->work);
}
EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);

View File

@ -1874,6 +1874,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
ifmsh->user_mpm = setup->user_mpm;
ifmsh->mesh_auth_id = setup->auth_id;
ifmsh->security = IEEE80211_MESH_SEC_NONE;
ifmsh->userspace_handles_dfs = setup->userspace_handles_dfs;
if (setup->is_authenticated)
ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
if (setup->is_secure)

View File

@ -152,6 +152,12 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
spin_lock_bh(&local->fq.lock);
rcu_read_lock();
p += scnprintf(p,
bufsz+buf-p,
"target %uus interval %uus ecn %s\n",
codel_time_to_us(sta->cparams.target),
codel_time_to_us(sta->cparams.interval),
sta->cparams.ecn ? "yes" : "no");
p += scnprintf(p,
bufsz+buf-p,
"tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n");

View File

@ -331,6 +331,18 @@ void ieee80211_ba_session_work(struct work_struct *work)
sta, tid, WLAN_BACK_RECIPIENT,
WLAN_REASON_UNSPECIFIED, true);
if (test_and_clear_bit(tid,
sta->ampdu_mlme.tid_rx_manage_offl))
__ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
IEEE80211_MAX_AMPDU_BUF,
false, true);
if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
sta->ampdu_mlme.tid_rx_manage_offl))
___ieee80211_stop_rx_ba_session(
sta, tid, WLAN_BACK_RECIPIENT,
0, false);
spin_lock_bh(&sta->lock);
tid_tx = sta->ampdu_mlme.tid_start_tx[tid];

View File

@ -808,7 +808,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
}
memset(&params, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems,
ifibss->chandef.chan->band,
sta_flags, ifibss->bssid, &csa_ie);

View File

@ -643,6 +643,8 @@ struct ieee80211_if_mesh {
unsigned long wrkq_flags;
unsigned long mbss_changed;
bool userspace_handles_dfs;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
/* Active Path Selection Protocol Identifier */
@ -1029,17 +1031,6 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif)
return shift;
}
struct ieee80211_rx_agg {
u8 addr[ETH_ALEN];
u16 tid;
};
enum sdata_queue_type {
IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
IEEE80211_SDATA_QUEUE_RX_AGG_START = 3,
IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4,
};
enum {
IEEE80211_RX_MSG = 1,
IEEE80211_TX_STATUS_MSG = 2,
@ -1432,6 +1423,7 @@ struct ieee80211_csa_ie {
u8 count;
u8 ttl;
u16 pre_value;
u16 reason_code;
};
/* Parsed Information Elements */
@ -2057,6 +2049,8 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
const struct cfg80211_chan_def *chandef,
u16 prot_mode, bool rifs_mode);
void ieee80211_ie_build_wide_bw_cs(u8 *pos,
const struct cfg80211_chan_def *chandef);
u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
u32 cap);
u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,

View File

@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work)
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct sta_info *sta;
struct ieee80211_rx_agg *rx_agg;
if (!ieee80211_sdata_running(sdata))
return;
@ -1252,28 +1251,8 @@ static void ieee80211_iface_work(struct work_struct *work)
while ((skb = skb_dequeue(&sdata->skb_queue))) {
struct ieee80211_mgmt *mgmt = (void *)skb->data;
if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
rx_agg = (void *)&skb->cb;
mutex_lock(&local->sta_mtx);
sta = sta_info_get_bss(sdata, rx_agg->addr);
if (sta)
__ieee80211_start_rx_ba_session(sta,
0, 0, 0, 1, rx_agg->tid,
IEEE80211_MAX_AMPDU_BUF,
false, true);
mutex_unlock(&local->sta_mtx);
} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
rx_agg = (void *)&skb->cb;
mutex_lock(&local->sta_mtx);
sta = sta_info_get_bss(sdata, rx_agg->addr);
if (sta)
__ieee80211_stop_rx_ba_session(sta,
rx_agg->tid,
WLAN_BACK_RECIPIENT, 0,
false);
mutex_unlock(&local->sta_mtx);
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK) {
if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK) {
int len = skb->len;
mutex_lock(&local->sta_mtx);

View File

@ -690,6 +690,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
2 + sizeof(struct ieee80211_channel_sw_ie) +
/* Mesh Channel Switch Parameters */
2 + sizeof(struct ieee80211_mesh_chansw_params_ie) +
/* Channel Switch Wrapper + Wide Bandwidth CSA IE */
2 + 2 + sizeof(struct ieee80211_wide_bw_chansw_ie) +
2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
2 + 8 + /* supported rates */
2 + 3; /* DS params */
tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
@ -736,8 +739,12 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
rcu_read_lock();
csa = rcu_dereference(ifmsh->csa);
if (csa) {
pos = skb_put(skb, 13);
memset(pos, 0, 13);
enum nl80211_channel_type ct;
struct cfg80211_chan_def *chandef;
int ie_len = 2 + sizeof(struct ieee80211_channel_sw_ie) +
2 + sizeof(struct ieee80211_mesh_chansw_params_ie);
pos = skb_put_zero(skb, ie_len);
*pos++ = WLAN_EID_CHANNEL_SWITCH;
*pos++ = 3;
*pos++ = 0x0;
@ -760,6 +767,37 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
pos += 2;
put_unaligned_le16(ifmsh->pre_value, pos);
pos += 2;
switch (csa->settings.chandef.width) {
case NL80211_CHAN_WIDTH_40:
ie_len = 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
pos = skb_put_zero(skb, ie_len);
*pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
*pos++ = 1; /* len */
ct = cfg80211_get_chandef_type(&csa->settings.chandef);
if (ct == NL80211_CHAN_HT40PLUS)
*pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
else
*pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break;
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160:
/* Channel Switch Wrapper + Wide Bandwidth CSA IE */
ie_len = 2 + 2 +
sizeof(struct ieee80211_wide_bw_chansw_ie);
pos = skb_put_zero(skb, ie_len);
*pos++ = WLAN_EID_CHANNEL_SWITCH_WRAPPER; /* EID */
*pos++ = 5; /* len */
/* put sub IE */
chandef = &csa->settings.chandef;
ieee80211_ie_build_wide_bw_cs(pos, chandef);
break;
default:
break;
}
}
rcu_read_unlock();
@ -916,6 +954,21 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
ieee80211_configure_filter(local);
}
static void ieee80211_mesh_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
{
int err;
/* if the current channel is a DFS channel, mark the channel as
* unavailable.
*/
err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
&sdata->vif.bss_conf.chandef,
NL80211_IFTYPE_MESH_POINT);
if (err > 0)
cfg80211_radar_event(sdata->local->hw.wiphy,
&sdata->vif.bss_conf.chandef, GFP_ATOMIC);
}
static bool
ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon)
@ -933,19 +986,20 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
if (!sband)
return false;
sta_flags = IEEE80211_STA_DISABLE_VHT;
sta_flags = 0;
switch (sdata->vif.bss_conf.chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
sta_flags |= IEEE80211_STA_DISABLE_HT;
case NL80211_CHAN_WIDTH_20:
sta_flags |= IEEE80211_STA_DISABLE_40MHZ;
case NL80211_CHAN_WIDTH_40:
sta_flags |= IEEE80211_STA_DISABLE_VHT;
break;
default:
break;
}
memset(&params, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
sta_flags, sdata->vif.addr,
&csa_ie);
@ -954,11 +1008,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
if (err)
return false;
/* Mark the channel unavailable if the reason for the switch is
* regulatory.
*/
if (csa_ie.reason_code == WLAN_REASON_MESH_CHAN_REGULATORY)
ieee80211_mesh_csa_mark_radar(sdata);
params.chandef = csa_ie.chandef;
params.count = csa_ie.count;
if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &params.chandef,
IEEE80211_CHAN_DISABLED)) {
IEEE80211_CHAN_DISABLED) ||
!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, &params.chandef,
NL80211_IFTYPE_MESH_POINT)) {
sdata_info(sdata,
"mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
sdata->vif.addr,
@ -974,9 +1036,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
NL80211_IFTYPE_MESH_POINT);
if (err < 0)
return false;
if (err > 0)
/* TODO: DFS not (yet) supported */
if (err > 0 && !ifmsh->userspace_handles_dfs) {
sdata_info(sdata,
"mesh STA %pM switches to channel requiring DFS (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
sdata->vif.addr,
params.chandef.chan->center_freq,
params.chandef.width,
params.chandef.center_freq1,
params.chandef.center_freq2);
return false;
}
params.radar_required = err;
@ -1233,7 +1302,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
pos = mgmt->u.action.u.chan_switch.variable;
baselen = offsetof(struct ieee80211_mgmt,
u.action.u.chan_switch.variable);
ieee802_11_parse_elems(pos, len - baselen, false, &elems);
ieee802_11_parse_elems(pos, len - baselen, true, &elems);
ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
if (!--ifmsh->chsw_ttl)

View File

@ -264,8 +264,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
band = sband->band;
/* capability info */
pos = skb_put(skb, 2);
memset(pos, 0, 2);
pos = skb_put_zero(skb, 2);
if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
/* AID */
pos = skb_put(skb, 2);

View File

@ -1126,7 +1126,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
return;
current_band = cbss->channel->band;
memset(&csa_ie, 0, sizeof(csa_ie));
res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
ifmgd->flags,
ifmgd->associated->bssid, &csa_ie);

View File

@ -943,6 +943,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
ieee80211_sta_set_expected_throughput(pubsta, sta_get_expected_throughput(sta));
return 0;
}
EXPORT_SYMBOL(rate_control_set_rates);
@ -991,4 +993,3 @@ void rate_control_deinitialize(struct ieee80211_local *local)
local->rate_ctrl = NULL;
rate_control_free(local, ref);
}

View File

@ -237,7 +237,6 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
if (!skb)
return;
skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
@ -1217,7 +1216,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
/* if this mpdu is fragmented - terminate rx aggregation session */
sc = le16_to_cpu(hdr->seq_ctrl);
if (sc & IEEE80211_SCTL_FRAG) {
skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&rx->sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &rx->sdata->work);
return;
@ -3100,7 +3098,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
return RX_QUEUED;
queue:
rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&local->hw, &sdata->work);
if (rx->sta)
@ -3246,7 +3243,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
}
/* queue up frame and kick off work to process it */
rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&rx->local->hw, &sdata->work);
if (rx->sta)

View File

@ -36,6 +36,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
int secondary_channel_offset = -1;
memset(csa_ie, 0, sizeof(*csa_ie));
sec_chan_offs = elems->sec_chan_offs;
wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
@ -76,6 +78,11 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
csa_ie->pre_value = le16_to_cpu(
elems->mesh_chansw_params_ie->mesh_pre_value);
if (elems->mesh_chansw_params_ie->mesh_flags &
WLAN_EID_CHAN_SWITCH_PARAM_REASON)
csa_ie->reason_code = le16_to_cpu(
elems->mesh_chansw_params_ie->mesh_reason);
}
new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);

View File

@ -20,6 +20,7 @@
#include <linux/timer.h>
#include <linux/rtnetlink.h>
#include <net/codel.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
@ -425,6 +426,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->sta.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA;
sta->cparams.ce_threshold = CODEL_DISABLED_THRESHOLD;
sta->cparams.target = MS2TIME(20);
sta->cparams.interval = MS2TIME(100);
sta->cparams.ecn = true;
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
return sta;
@ -2310,3 +2316,27 @@ unsigned long ieee80211_sta_last_active(struct sta_info *sta)
return stats->last_rx;
return sta->status_stats.last_ack;
}
static void sta_update_codel_params(struct sta_info *sta, u32 thr)
{
if (!sta->sdata->local->ops->wake_tx_queue)
return;
if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
sta->cparams.target = MS2TIME(50);
sta->cparams.interval = MS2TIME(300);
sta->cparams.ecn = false;
} else {
sta->cparams.target = MS2TIME(20);
sta->cparams.interval = MS2TIME(100);
sta->cparams.ecn = true;
}
}
void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
u32 thr)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
sta_update_codel_params(sta, thr);
}

View File

@ -233,6 +233,8 @@ struct tid_ampdu_rx {
* RX timer expired until the work for it runs
* @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the
* driver requested to close until the work for it runs
* @tid_rx_manage_offl: bitmap indicating which BA sessions were requested
* to be treated as started/stopped due to offloading
* @agg_session_valid: bitmap indicating which TID has a rx BA session open on
* @unexpected_agg: bitmap indicating which TID already sent a delBA due to
* unexpected aggregation related frames outside a session
@ -250,6 +252,7 @@ struct sta_ampdu_mlme {
u8 tid_rx_token[IEEE80211_NUM_TIDS];
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long tid_rx_manage_offl[BITS_TO_LONGS(2 * IEEE80211_NUM_TIDS)];
unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long unexpected_agg[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
/* tx */
@ -395,6 +398,14 @@ struct ieee80211_sta_rx_stats {
u64 msdu[IEEE80211_NUM_TIDS + 1];
};
/**
* The bandwidth threshold below which the per-station CoDel parameters will be
* scaled to be more lenient (to prevent starvation of slow stations). This
* value will be scaled by the number of active stations when it is being
* applied.
*/
#define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
/**
* struct sta_info - STA information
*
@ -448,6 +459,7 @@ struct ieee80211_sta_rx_stats {
* @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
* AP only.
* @cipher_scheme: optional cipher scheme for this station
* @cparams: CoDel parameters for this station.
* @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
* @fast_tx: TX fastpath information
* @fast_rx: RX fastpath information
@ -551,6 +563,8 @@ struct sta_info {
enum ieee80211_smps_mode known_smps_mode;
const struct ieee80211_cipher_scheme *cipher_scheme;
struct codel_params cparams;
u8 reserved_tid;
struct cfg80211_chan_def tdls_chandef;

View File

@ -546,6 +546,8 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
skb->wifi_acked_valid = 1;
skb->wifi_acked = acked;
}
ieee80211_led_tx(local);
}
/*
@ -823,8 +825,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
}
}
ieee80211_led_tx(local);
/* SNMP counters
* Fragments are passed to low-level drivers as separate skbs, so these
* are actually fragments, not frames. Update frame counters only for

View File

@ -92,16 +92,19 @@
__field(u16, ssn) \
__field(u8, buf_size) \
__field(bool, amsdu) \
__field(u16, timeout)
__field(u16, timeout) \
__field(u16, action)
#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \
__entry->tid = params->tid; \
__entry->ssn = params->ssn; \
__entry->buf_size = params->buf_size; \
__entry->amsdu = params->amsdu; \
__entry->timeout = params->timeout;
#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d"
__entry->timeout = params->timeout; \
__entry->action = params->action;
#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d action %d"
#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \
__entry->buf_size, __entry->amsdu, __entry->timeout
__entry->buf_size, __entry->amsdu, __entry->timeout, \
__entry->action
/*
* Tracing for driver callbacks.

View File

@ -1340,9 +1340,16 @@ static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
local = container_of(fq, struct ieee80211_local, fq);
txqi = container_of(tin, struct txq_info, tin);
cparams = &local->cparams;
cstats = &txqi->cstats;
if (txqi->txq.sta) {
struct sta_info *sta = container_of(txqi->txq.sta,
struct sta_info, sta);
cparams = &sta->cparams;
} else {
cparams = &local->cparams;
}
if (flow == &txqi->def_flow)
cvars = &txqi->def_cvars;
else

View File

@ -2414,6 +2414,35 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
return pos + sizeof(struct ieee80211_ht_operation);
}
void ieee80211_ie_build_wide_bw_cs(u8 *pos,
const struct cfg80211_chan_def *chandef)
{
*pos++ = WLAN_EID_WIDE_BW_CHANNEL_SWITCH; /* EID */
*pos++ = 3; /* IE length */
/* New channel width */
switch (chandef->width) {
case NL80211_CHAN_WIDTH_80:
*pos++ = IEEE80211_VHT_CHANWIDTH_80MHZ;
break;
case NL80211_CHAN_WIDTH_160:
*pos++ = IEEE80211_VHT_CHANWIDTH_160MHZ;
break;
case NL80211_CHAN_WIDTH_80P80:
*pos++ = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
break;
default:
*pos++ = IEEE80211_VHT_CHANWIDTH_USE_HT;
}
/* new center frequency segment 0 */
*pos++ = ieee80211_frequency_to_channel(chandef->center_freq1);
/* new center frequency segment 1 */
if (chandef->center_freq2)
*pos++ = ieee80211_frequency_to_channel(chandef->center_freq2);
else
*pos++ = 0;
}
u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
const struct cfg80211_chan_def *chandef)
{
@ -2964,6 +2993,7 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
skb = dev_alloc_skb(local->tx_headroom + hdr_len +
5 + /* channel switch announcement element */
3 + /* secondary channel offset element */
5 + /* wide bandwidth channel switch announcement */
8); /* mesh channel switch parameters element */
if (!skb)
return -ENOMEM;
@ -3022,6 +3052,13 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
pos += 2;
}
if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_80 ||
csa_settings->chandef.width == NL80211_CHAN_WIDTH_80P80 ||
csa_settings->chandef.width == NL80211_CHAN_WIDTH_160) {
skb_put(skb, 5);
ieee80211_ie_build_wide_bw_cs(pos, &csa_settings->chandef);
}
ieee80211_tx_skb(sdata, skb);
return 0;
}

View File

@ -81,8 +81,7 @@ static int rfkill_gpio_acpi_probe(struct device *dev,
rfkill->type = (unsigned)id->driver_data;
return acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
acpi_rfkill_default_gpios);
return devm_acpi_dev_add_driver_gpios(dev, acpi_rfkill_default_gpios);
}
static int rfkill_gpio_probe(struct platform_device *pdev)
@ -154,8 +153,6 @@ static int rfkill_gpio_remove(struct platform_device *pdev)
rfkill_unregister(rfkill->rfkill_dev);
rfkill_destroy(rfkill->rfkill_dev);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
return 0;
}

View File

@ -711,6 +711,11 @@ int wiphy_register(struct wiphy *wiphy)
(wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
return -EINVAL;
if (WARN_ON(wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X) &&
(!rdev->ops->set_pmk || !rdev->ops->del_pmk)))
return -EINVAL;
if (wiphy->addresses)
memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);

View File

@ -174,6 +174,14 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
scan_width);
}
err = cfg80211_chandef_dfs_required(&rdev->wiphy,
&setup->chandef,
NL80211_IFTYPE_MESH_POINT);
if (err < 0)
return err;
if (err > 0 && !setup->userspace_handles_dfs)
return -EINVAL;
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef,
NL80211_IFTYPE_MESH_POINT))
return -EINVAL;

View File

@ -7501,6 +7501,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
int err;
bool need_new_beacon = false;
bool need_handle_dfs_flag = true;
int len, i;
u32 cs_count;
@ -7512,6 +7513,12 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
need_new_beacon = true;
/* For all modes except AP the handle_dfs flag needs to be
* supplied to tell the kernel that userspace will handle radar
* events when they happen. Otherwise a switch to a channel
* requiring DFS will be rejected.
*/
need_handle_dfs_flag = false;
/* useless if AP is not running */
if (!wdev->beacon_interval)
@ -7634,8 +7641,13 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (err < 0)
return err;
if (err > 0)
if (err > 0) {
params.radar_required = true;
if (need_handle_dfs_flag &&
!nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
return -EINVAL;
}
}
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
params.block_tx = true;
@ -8156,6 +8168,15 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
memcpy(settings->akm_suites, data, len);
}
if (info->attrs[NL80211_ATTR_PMK]) {
if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
return -EINVAL;
if (!wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
return -EINVAL;
settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
}
return 0;
}
@ -8860,6 +8881,12 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
!wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
return -EINVAL;
connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
err = nl80211_crypto_settings(rdev, info, &connect.crypto,
NL80211_MAX_NR_CIPHER_SUITES);
if (err)
@ -9962,6 +9989,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
return err;
}
setup.userspace_handles_dfs =
nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
}
@ -12241,6 +12271,90 @@ static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
return rdev_set_multicast_to_unicast(rdev, dev, enabled);
}
static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_pmk_conf pmk_conf = {};
int ret;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
return -EOPNOTSUPP;
if (!wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
return -EOPNOTSUPP;
if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
return -EINVAL;
wdev_lock(wdev);
if (!wdev->current_bss) {
ret = -ENOTCONN;
goto out;
}
pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
ret = -EINVAL;
goto out;
}
pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
ret = -EINVAL;
goto out;
}
if (info->attrs[NL80211_ATTR_PMKR0_NAME]) {
int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]);
if (r0_name_len != WLAN_PMK_NAME_LEN) {
ret = -EINVAL;
goto out;
}
pmk_conf.pmk_r0_name =
nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
}
ret = rdev_set_pmk(rdev, dev, &pmk_conf);
out:
wdev_unlock(wdev);
return ret;
}
static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
const u8 *aa;
int ret;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
return -EOPNOTSUPP;
if (!wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
return -EOPNOTSUPP;
if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;
wdev_lock(wdev);
aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
ret = rdev_del_pmk(rdev, dev, aa);
wdev_unlock(wdev);
return ret;
}
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@ -13116,6 +13230,21 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_PMK,
.doit = nl80211_set_pmk,
.policy = nl80211_policy,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_DEL_PMK,
.doit = nl80211_del_pmk,
.policy = nl80211_policy,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
};
static struct genl_family nl80211_fam __ro_after_init = {
@ -13671,7 +13800,9 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
info->req_ie)) ||
(info->resp_ie &&
nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
info->resp_ie)))
info->resp_ie)) ||
(info->authorized &&
nla_put_flag(msg, NL80211_ATTR_PORT_AUTHORIZED)))
goto nla_put_failure;
genlmsg_end(msg, hdr);

View File

@ -1164,4 +1164,29 @@ rdev_set_coalesce(struct cfg80211_registered_device *rdev,
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline int rdev_set_pmk(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_pmk_conf *pmk_conf)
{
int ret = -EOPNOTSUPP;
trace_rdev_set_pmk(&rdev->wiphy, dev, pmk_conf);
if (rdev->ops->set_pmk)
ret = rdev->ops->set_pmk(&rdev->wiphy, dev, pmk_conf);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *aa)
{
int ret = -EOPNOTSUPP;
trace_rdev_del_pmk(&rdev->wiphy, dev, aa);
if (rdev->ops->del_pmk)
ret = rdev->ops->del_pmk(&rdev->wiphy, dev, aa);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
#endif /* __CFG80211_RDEV_OPS */

View File

@ -960,6 +960,7 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
ev->rm.resp_ie_len = info->resp_ie_len;
memcpy((void *)ev->rm.resp_ie, info->resp_ie, info->resp_ie_len);
ev->rm.bss = info->bss;
ev->rm.authorized = info->authorized;
spin_lock_irqsave(&wdev->event_lock, flags);
list_add_tail(&ev->list, &wdev->event_list);

View File

@ -2258,6 +2258,66 @@ TRACE_EVENT(rdev_tdls_cancel_channel_switch,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
);
TRACE_EVENT(rdev_set_pmk,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_pmk_conf *pmk_conf),
TP_ARGS(wiphy, netdev, pmk_conf),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
MAC_ENTRY(aa)
__field(u8, pmk_len)
__field(u8, pmk_r0_name_len)
__dynamic_array(u8, pmk, pmk_conf->pmk_len)
__dynamic_array(u8, pmk_r0_name, WLAN_PMK_NAME_LEN)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
MAC_ASSIGN(aa, pmk_conf->aa);
__entry->pmk_len = pmk_conf->pmk_len;
__entry->pmk_r0_name_len =
pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0;
memcpy(__get_dynamic_array(pmk), pmk_conf->pmk,
pmk_conf->pmk_len);
memcpy(__get_dynamic_array(pmk_r0_name), pmk_conf->pmk_r0_name,
pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0);
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT
"pmk_len=%u, pmk: %s pmk_r0_name: %s", WIPHY_PR_ARG,
NETDEV_PR_ARG, MAC_PR_ARG(aa), __entry->pmk_len,
__print_array(__get_dynamic_array(pmk),
__get_dynamic_array_len(pmk), 1),
__entry->pmk_r0_name_len ?
__print_array(__get_dynamic_array(pmk_r0_name),
__get_dynamic_array_len(pmk_r0_name), 1) : "")
);
TRACE_EVENT(rdev_del_pmk,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *aa),
TP_ARGS(wiphy, netdev, aa),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
MAC_ENTRY(aa)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
MAC_ASSIGN(aa, aa);
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa))
);
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/

View File

@ -1219,8 +1219,8 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
u32 bitrate;
int idx;
if (WARN_ON_ONCE(rate->mcs > 9))
return 0;
if (rate->mcs > 9)
goto warn;
switch (rate->bw) {
case RATE_INFO_BW_160:
@ -1235,8 +1235,7 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
case RATE_INFO_BW_5:
case RATE_INFO_BW_10:
default:
WARN_ON(1);
/* fall through */
goto warn;
case RATE_INFO_BW_20:
idx = 0;
}
@ -1249,6 +1248,10 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
/* do NOT round down here */
return (bitrate + 50000) / 100000;
warn:
WARN_ONCE(1, "invalid rate bw=%d, mcs=%d, nss=%d\n",
rate->bw, rate->mcs, rate->nss);
return 0;
}
u32 cfg80211_calculate_bitrate(struct rate_info *rate)