mac80211: improve ad-hoc multicast rate handling
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 550-cfg80211_validate_mcast_rate.patch
1 --- a/include/net/cfg80211.h
2 +++ b/include/net/cfg80211.h
3 @@ -924,7 +924,7 @@ struct cfg80211_disassoc_request {
4 * @privacy: this is a protected network, keys will be configured
5 * after joining
6 * @basic_rates: bitmap of basic rates to use when creating the IBSS
7 - * @mcast_rate: multicast tx rate (in 100 kbps)
8 + * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
9 */
10 struct cfg80211_ibss_params {
11 u8 *ssid;
12 @@ -936,7 +936,7 @@ struct cfg80211_ibss_params {
13 u32 basic_rates;
14 bool channel_fixed;
15 bool privacy;
16 - int mcast_rate;
17 + int mcast_rate[IEEE80211_NUM_BANDS];
18 };
19
20 /**
21 --- a/include/net/mac80211.h
22 +++ b/include/net/mac80211.h
23 @@ -219,7 +219,7 @@ enum ieee80211_bss_change {
24 * @basic_rates: bitmap of basic rates, each bit stands for an
25 * index into the rate table configured by the driver in
26 * the current band.
27 - * @mcast_rate: multicast rate for AP and Ad-Hoc (in 100 kbps)
28 + * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
29 * @bssid: The BSSID for this BSS
30 * @enable_beacon: whether beaconing should be enabled or not
31 * @channel_type: Channel type for this BSS -- the hardware might be
32 @@ -259,7 +259,7 @@ struct ieee80211_bss_conf {
33 u16 assoc_capability;
34 u64 timestamp;
35 u32 basic_rates;
36 - u32 mcast_rate;
37 + int mcast_rate[IEEE80211_NUM_BANDS];
38 u16 ht_operation_mode;
39 s32 cqm_rssi_thold;
40 u32 cqm_rssi_hyst;
41 --- a/net/mac80211/ibss.c
42 +++ b/net/mac80211/ibss.c
43 @@ -915,7 +915,8 @@ int ieee80211_ibss_join(struct ieee80211
44
45 sdata->u.ibss.privacy = params->privacy;
46 sdata->u.ibss.basic_rates = params->basic_rates;
47 - sdata->vif.bss_conf.mcast_rate = params->mcast_rate;
48 + memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate,
49 + sizeof(params->mcast_rate));
50
51 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
52
53 --- a/net/mac80211/rate.c
54 +++ b/net/mac80211/rate.c
55 @@ -211,20 +211,11 @@ static bool rc_no_data_or_no_ack(struct
56 return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc);
57 }
58
59 -static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u32 mcast_rate,
60 +static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
61 struct ieee80211_supported_band *sband)
62 {
63 u8 i;
64
65 - if (mcast_rate) {
66 - for (i = 0; i < sband->n_bitrates; i++) {
67 - if (sband->bitrates[i].bitrate == mcast_rate) {
68 - *idx = i;
69 - return;
70 - }
71 - }
72 - }
73 -
74 if (basic_rates == 0)
75 return; /* assume basic rates unknown and accept rate */
76 if (*idx < 0)
77 @@ -247,17 +238,25 @@ bool rate_control_send_low(struct ieee80
78 struct ieee80211_tx_rate_control *txrc)
79 {
80 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
81 + struct ieee80211_supported_band *sband = txrc->sband;
82 + int mcast_rate;
83
84 if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) {
85 info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta);
86 info->control.rates[0].count =
87 (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
88 1 : txrc->hw->max_rate_tries;
89 - if (!sta && txrc->bss)
90 + if (!sta && txrc->bss) {
91 + mcast_rate = txrc->bss_conf->mcast_rate[sband->band];
92 + if (mcast_rate > 0) {
93 + info->control.rates[0].idx = mcast_rate - 1;
94 + return true;
95 + }
96 +
97 rc_send_low_broadcast(&info->control.rates[0].idx,
98 txrc->bss_conf->basic_rates,
99 - txrc->bss_conf->mcast_rate,
100 - txrc->sband);
101 + sband);
102 + }
103 return true;
104 }
105 return false;
106 --- a/net/wireless/nl80211.c
107 +++ b/net/wireless/nl80211.c
108 @@ -3600,6 +3600,34 @@ static int nl80211_disassociate(struct s
109 local_state_change);
110 }
111
112 +static bool
113 +nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
114 + int mcast_rate[IEEE80211_NUM_BANDS],
115 + int rateval)
116 +{
117 + struct wiphy *wiphy = &rdev->wiphy;
118 + bool found = false;
119 + int band, i;
120 +
121 + for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
122 + struct ieee80211_supported_band *sband;
123 +
124 + sband = wiphy->bands[band];
125 + if (!sband)
126 + continue;
127 +
128 + for (i = 0; i < sband->n_bitrates; i++) {
129 + if (sband->bitrates[i].bitrate == rateval) {
130 + mcast_rate[band] = i + 1;
131 + found = true;
132 + break;
133 + }
134 + }
135 + }
136 +
137 + return found;
138 +}
139 +
140 static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
141 {
142 struct cfg80211_registered_device *rdev = info->user_ptr[0];
143 @@ -3683,9 +3711,11 @@ static int nl80211_join_ibss(struct sk_b
144 return -EINVAL;
145 }
146 }
147 - if (info->attrs[NL80211_ATTR_MCAST_RATE])
148 - ibss.mcast_rate =
149 - nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
150 +
151 + if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
152 + !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
153 + nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
154 + return -EINVAL;
155
156 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
157 connkeys = nl80211_parse_connkeys(rdev,