Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2e506bf authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: parse VHT channel switch IEs



VHT introduces multiple IEs that need to be parsed for a
wide bandwidth channel switch. Two are (currently) needed
in mac80211:
 * wide bandwidth channel switch element
 * channel switch wrapper element

The former is contained in the latter for beacons and probe
responses, but not for the spectrum management action frames
so the IE parser needs a new argument to differentiate them.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 1b3a2e49
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -694,6 +694,14 @@ struct ieee80211_sec_chan_offs_ie {
	u8 sec_chan_offs;
	u8 sec_chan_offs;
} __packed;
} __packed;


/**
 * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
 */
struct ieee80211_wide_bw_chansw_ie {
	u8 new_channel_width;
	u8 new_center_freq_seg0, new_center_freq_seg1;
} __packed;

/**
/**
 * struct ieee80211_tim
 * struct ieee80211_tim
 *
 *
@@ -1698,6 +1706,8 @@ enum ieee80211_eid {
	WLAN_EID_VHT_CAPABILITY = 191,
	WLAN_EID_VHT_CAPABILITY = 191,
	WLAN_EID_VHT_OPERATION = 192,
	WLAN_EID_VHT_OPERATION = 192,
	WLAN_EID_OPMODE_NOTIF = 199,
	WLAN_EID_OPMODE_NOTIF = 199,
	WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
	WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,


	/* 802.11ad */
	/* 802.11ad */
	WLAN_EID_NON_TX_BSSID_CAP =  83,
	WLAN_EID_NON_TX_BSSID_CAP =  83,
+1 −1
Original line number Original line Diff line number Diff line
@@ -914,7 +914,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
		return;
		return;


	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
				&elems);
			       false, &elems);


	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
}
}
+4 −3
Original line number Original line Diff line number Diff line
@@ -1179,6 +1179,7 @@ struct ieee802_11_elems {
	const struct ieee80211_rann_ie *rann;
	const struct ieee80211_rann_ie *rann;
	const struct ieee80211_channel_sw_ie *ch_switch_ie;
	const struct ieee80211_channel_sw_ie *ch_switch_ie;
	const struct ieee80211_ext_chansw_ie *ext_chansw_ie;
	const struct ieee80211_ext_chansw_ie *ext_chansw_ie;
	const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
	const u8 *country_elem;
	const u8 *country_elem;
	const u8 *pwr_constr_elem;
	const u8 *pwr_constr_elem;
	const struct ieee80211_timeout_interval_ie *timeout_int;
	const struct ieee80211_timeout_interval_ie *timeout_int;
@@ -1490,13 +1491,13 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
	ieee80211_tx_skb_tid(sdata, skb, 7);
	ieee80211_tx_skb_tid(sdata, skb, 7);
}
}


u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
			       struct ieee802_11_elems *elems,
			       struct ieee802_11_elems *elems,
			       u64 filter, u32 crc);
			       u64 filter, u32 crc);
static inline void ieee802_11_parse_elems(u8 *start, size_t len,
static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
					  struct ieee802_11_elems *elems)
					  struct ieee802_11_elems *elems)
{
{
	ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
	ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
}
}


u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
+2 −2
Original line number Original line Diff line number Diff line
@@ -838,7 +838,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
	if (baselen > len)
	if (baselen > len)
		return;
		return;


	ieee802_11_parse_elems(pos, len - baselen, &elems);
	ieee802_11_parse_elems(pos, len - baselen, false, &elems);


	/* 802.11-2012 10.1.4.3.2 */
	/* 802.11-2012 10.1.4.3.2 */
	if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
	if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
@@ -899,7 +899,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
		return;
		return;


	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
			       &elems);
			       false, &elems);


	/* ignore non-mesh or secure / unsecure mismatch */
	/* ignore non-mesh or secure / unsecure mismatch */
	if ((!elems.mesh_id || !elems.mesh_config) ||
	if ((!elems.mesh_id || !elems.mesh_config) ||
+1 −1
Original line number Original line Diff line number Diff line
@@ -880,7 +880,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,


	baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
	baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
	ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
	ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
			len - baselen, &elems);
			       len - baselen, false, &elems);


	if (elems.preq) {
	if (elems.preq) {
		if (elems.preq_len != 37)
		if (elems.preq_len != 37)
Loading