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
32 changed files with 620 additions and 111 deletions
+4
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
+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)
{
+42
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;
};
/**
+33 -4
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 */
+69 -4
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,
+12 -35
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);
+1
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)
+6
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");
+12
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];
-1
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);
+5 -11
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,
+2 -23
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);
+77 -8
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)
+1 -2
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);
-1
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);
+2 -1
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);
}
-4
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)
+7
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);
+30
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);
}
+14
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;

Some files were not shown because too many files have changed in this diff Show More