History

cfg80211: pass station supported channel and oper class info

The information of the peer's supported channels and supported operating classes are required for the driver to perform TDLS off channel operations. This commit enhances the function nl80211_(new)set_station to pass this information of the peer to the driver.

Sunil Dutt committed 13 years ago

Commit c01fc9a1 parent 789fd033 files · +63 −0Browse files

Unified · Split

3 files
  1. include/net/cfg80211.h +8 −0
  2. include/uapi/linux/nl80211.h +9 −0
  3. net/wireless/nl80211.c +46 −0
include/net/cfg80211.h+8−0
@@ -744,6 +744,10 @@ enum station_parameters_apply_mask { · 743 unmodified lines
744744 * @capability: station capability
745745 * @ext_capab: extended capabilities of the station
746746 * @ext_capab_len: number of extended capabilities
747+ * @supported_channels: supported channels in IEEE 802.11 format
748+ * @supported_channels_len: number of supported channels
749+ * @supported_oper_classes: supported oper classes in IEEE 802.11 format
750+ * @supported_oper_classes_len: number of supported operating classes
747751 */
748752 struct station_parameters {
749753 const u8 *supported_rates;
@@ -763,6 +767,10 @@ struct station_parameters { · 13 unmodified lines
763767 u16 capability;
764768 const u8 *ext_capab;
765769 u8 ext_capab_len;
770+ const u8 *supported_channels;
771+ u8 supported_channels_len;
772+ const u8 *supported_oper_classes;
773+ u8 supported_oper_classes_len;
766774 };
767775
768776 /**
include/uapi/linux/nl80211.h+9−0
@@ -1496,6 +1496,11 @@ enum nl80211_commands { · 1495 unmodified lines
14961496 * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
14971497 * As specified in the &enum nl80211_rxmgmt_flags.
14981498 *
1499+ * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels.
1500+ *
1501+ * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported
1502+ * supported operating classes.
1503+ *
14991504 * @NL80211_ATTR_MAX: highest attribute number currently defined
15001505 * @__NL80211_ATTR_AFTER_LAST: internal use
15011506 */
@@ -1806,6 +1811,10 @@ enum nl80211_attrs { · 304 unmodified lines
18061811
18071812 NL80211_ATTR_RXMGMT_FLAGS,
18081813
1814+ NL80211_ATTR_STA_SUPPORTED_CHANNELS,
1815+
1816+ NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
1817+
18091818 /* add attributes here, update the policy in nl80211.c */
18101819
18111820 __NL80211_ATTR_AFTER_LAST,
net/wireless/nl80211.c+46−0
@@ -354,6 +354,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { · 353 unmodified lines
354354 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
355355 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
356356 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
357+ [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
358+ [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
357359 };
358360
359361 /* policy for the key attributes */
@@ -3896,9 +3898,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info, · 3536 unmodified lines
38963898 return 0;
38973899 }
38983900
3901+static int nl80211_parse_sta_channel_info(struct genl_info *info,
3902+ struct station_parameters *params)
3903+{
3904+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
3905+ params->supported_channels =
3906+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
3907+ params->supported_channels_len =
3908+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
3909+ /*
3910+ * Need to include at least one (first channel, number of
3911+ * channels) tuple for each subband, and must have proper
3912+ * tuples for the rest of the data as well.
3913+ */
3914+ if (params->supported_channels_len < 2)
3915+ return -EINVAL;
3916+ if (params->supported_channels_len % 2)
3917+ return -EINVAL;
3918+ }
3919+
3920+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
3921+ params->supported_oper_classes =
3922+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
3923+ params->supported_oper_classes_len =
3924+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
3925+ /*
3926+ * The value of the Length field of the Supported Operating
3927+ * Classes element is between 2 and 253.
3928+ */
3929+ if (params->supported_oper_classes_len < 2 ||
3930+ params->supported_oper_classes_len > 253)
3931+ return -EINVAL;
3932+ }
3933+ return 0;
3934+}
3935+
38993936 static int nl80211_set_station_tdls(struct genl_info *info,
39003937 struct station_parameters *params)
39013938 {
3939+ int err;
39023940 /* Dummy STA entry gets updated once the peer capabilities are known */
39033941 if (info->attrs[NL80211_ATTR_PEER_AID])
39043942 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
@@ -3909,6 +3947,10 @@ static int nl80211_set_station_tdls(struct genl_info *info, · 4 unmodified lines
39093947 params->vht_capa =
39103948 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
39113949
3950+ err = nl80211_parse_sta_channel_info(info, params);
3951+ if (err)
3952+ return err;
3953+
39123954 return nl80211_parse_sta_wme(info, params);
39133955 }
39143956
@@ -4089,6 +4131,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 174 unmodified lines
40894131 return -EINVAL;
40904132 }
40914133
4134+ err = nl80211_parse_sta_channel_info(info, &params);
4135+ if (err)
4136+ return err;
4137+
40924138 err = nl80211_parse_sta_wme(info, &params);
40934139 if (err)
40944140 return err;