History

cfg80211: regulatory: allow getting DFS CAC time from userspace

Introduce DFS CAC time as a regd param, configured per REG_RULE and set per channel in cfg80211. DFS CAC time is close connected with regulatory database configuration. Instead of using hardcoded values, get DFS CAC time form regulatory database. Pass DFS CAC time to user mode (mainly for iw reg get, iw list, iw info). Allow setting DFS CAC time via CRDA. Add support for internal regulatory database.

Janusz Dziedzic committed 12 years ago

Commit 089027e1 parent fb5c9636 files · +66 −16Browse files

Unified · Split

6 files
  1. include/net/cfg80211.h +2 −0
  2. include/net/regulatory.h +13 −8
  3. include/uapi/linux/nl80211.h +6 −0
  4. net/wireless/genregdb.awk +7 −1
  5. net/wireless/nl80211.c +12 −1
  6. net/wireless/reg.c +26 −6
include/net/cfg80211.h+2−0
@@ -151,6 +151,7 @@ enum ieee80211_channel_flags { · 150 unmodified lines
151151 * @dfs_state: current state of this channel. Only relevant if radar is required
152152 * on this channel.
153153 * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
154+ * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
154155 */
155156 struct ieee80211_channel {
156157 enum ieee80211_band band;
@@ -165,6 +166,7 @@ struct ieee80211_channel { · 8 unmodified lines
165166 int orig_mag, orig_mpwr;
166167 enum nl80211_dfs_state dfs_state;
167168 unsigned long dfs_state_entered;
169+ unsigned int dfs_cac_ms;
168170 };
169171
170172 /**
include/net/regulatory.h+13−8
@@ -155,6 +155,7 @@ struct ieee80211_reg_rule { · 154 unmodified lines
155155 struct ieee80211_freq_range freq_range;
156156 struct ieee80211_power_rule power_rule;
157157 u32 flags;
158+ u32 dfs_cac_ms;
158159 };
159160
160161 struct ieee80211_regdomain {
@@ -172,14 +173,18 @@ struct ieee80211_regdomain { · 11 unmodified lines
172173 #define DBM_TO_MBM(gain) ((gain) * 100)
173174 #define MBM_TO_DBM(gain) ((gain) / 100)
174175
175−#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
176−{ \
177− .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
178− .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \
179− .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
180− .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\
181− .power_rule.max_eirp = DBM_TO_MBM(eirp), \
182− .flags = reg_flags, \
176+#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \
177+{ \
178+ .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
179+ .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \
180+ .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
181+ .power_rule.max_antenna_gain = DBI_TO_MBI(gain), \
182+ .power_rule.max_eirp = DBM_TO_MBM(eirp), \
183+ .flags = reg_flags, \
184+ .dfs_cac_ms = dfs_cac, \
183185 }
184186
187+#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
188+ REG_RULE_EXT(start, end, bw, gain, eirp, 0, reg_flags)
189+
185190 #endif
include/uapi/linux/nl80211.h+6−0
@@ -2335,6 +2335,7 @@ enum nl80211_band_attr { · 2334 unmodified lines
23352335 * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel
23362336 * using this channel as the primary or any of the secondary channels
23372337 * isn't possible
2338+ * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
23382339 * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
23392340 * currently defined
23402341 * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -2353,6 +2354,7 @@ enum nl80211_frequency_attr { · 12 unmodified lines
23532354 NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
23542355 NL80211_FREQUENCY_ATTR_NO_80MHZ,
23552356 NL80211_FREQUENCY_ATTR_NO_160MHZ,
2357+ NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
23562358
23572359 /* keep last */
23582360 __NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -2449,6 +2451,8 @@ enum nl80211_reg_type { · 90 unmodified lines
24492451 * If you don't have one then don't send this.
24502452 * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
24512453 * a given frequency range. The value is in mBm (100 * dBm).
2454+ * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
2455+ * If not present or 0 default CAC time will be used.
24522456 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
24532457 * currently defined
24542458 * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -2464,6 +2468,8 @@ enum nl80211_reg_rule_attr { · 9 unmodified lines
24642468 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
24652469 NL80211_ATTR_POWER_RULE_MAX_EIRP,
24662470
2471+ NL80211_ATTR_DFS_CAC_TIME,
2472+
24672473 /* keep last */
24682474 __NL80211_REG_RULE_ATTR_AFTER_LAST,
24692475 NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
net/wireless/genregdb.awk+7−1
@@ -66,6 +66,7 @@ function parse_reg_rule() · 65 unmodified lines
6666 units = $8
6767 sub(/\)/, "", units)
6868 sub(/,/, "", units)
69+ dfs_cac = $9
6970 if (units == "mW") {
7071 if (power == 100) {
7172 power = 20
@@ -78,7 +79,12 @@ function parse_reg_rule() · 6 unmodified lines
7879 } else {
7980 print "Unknown power value in database!"
8081 }
82+ } else {
83+ dfs_cac = $8
8184 }
85+ sub(/,/, "", dfs_cac)
86+ sub(/\(/, "", dfs_cac)
87+ sub(/\)/, "", dfs_cac)
8288 flagstr = ""
8389 for (i=8; i<=NF; i++)
8490 flagstr = flagstr $i
@@ -111,7 +117,7 @@ function parse_reg_rule() · 26 unmodified lines
111117
112118 }
113119 flags = flags "0"
114− printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
120+ printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
115121 rules++
116122 }
117123
net/wireless/nl80211.c+12−1
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, · 592 unmodified lines
593593 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
594594 time))
595595 goto nla_put_failure;
596+ if (nla_put_u32(msg,
597+ NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
598+ chan->dfs_cac_ms))
599+ goto nla_put_failure;
596600 }
597601 }
598602
@@ -4614,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = · 4015 unmodified lines
46144618 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
46154619 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
46164620 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
4621+ [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
46174622 };
46184623
46194624 static int parse_reg_rule(struct nlattr *tb[],
@@ -4649,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[], · 29 unmodified lines
46494654 power_rule->max_antenna_gain =
46504655 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
46514656
4657+ if (tb[NL80211_ATTR_DFS_CAC_TIME])
4658+ reg_rule->dfs_cac_ms =
4659+ nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
4660+
46524661 return 0;
46534662 }
46544663
@@ -5136,7 +5145,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) · 481 unmodified lines
51365145 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
51375146 power_rule->max_antenna_gain) ||
51385147 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
5139− power_rule->max_eirp))
5148+ power_rule->max_eirp) ||
5149+ nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
5150+ reg_rule->dfs_cac_ms))
51405151 goto nla_put_failure_rcu;
51415152
51425153 nla_nest_end(msg, nl_reg_rule);
net/wireless/reg.c+26−6
@@ -756,6 +756,9 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, · 755 unmodified lines
756756 power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
757757 power_rule2->max_antenna_gain);
758758
759+ intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
760+ rule2->dfs_cac_ms);
761+
759762 if (!is_valid_reg_rule(intersected_rule))
760763 return -EINVAL;
761764
@@ -1078,6 +1081,14 @@ static void handle_channel(struct wiphy *wiphy, · 316 unmodified lines
10781081 min_t(int, chan->orig_mag,
10791082 MBI_TO_DBI(power_rule->max_antenna_gain));
10801083 chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1084+
1085+ if (chan->flags & IEEE80211_CHAN_RADAR) {
1086+ if (reg_rule->dfs_cac_ms)
1087+ chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
1088+ else
1089+ chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
1090+ }
1091+
10811092 if (chan->orig_mpwr) {
10821093 /*
10831094 * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
@@ -2256,9 +2267,9 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) · 1172 unmodified lines
22562267 const struct ieee80211_reg_rule *reg_rule = NULL;
22572268 const struct ieee80211_freq_range *freq_range = NULL;
22582269 const struct ieee80211_power_rule *power_rule = NULL;
2259− char bw[32];
2270+ char bw[32], cac_time[32];
22602271
2261− pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
2272+ pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
22622273
22632274 for (i = 0; i < rd->n_reg_rules; i++) {
22642275 reg_rule = &rd->reg_rules[i];
@@ -2273,23 +2284,32 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) · 8 unmodified lines
22732284 snprintf(bw, sizeof(bw), "%d KHz",
22742285 freq_range->max_bandwidth_khz);
22752286
2287+ if (reg_rule->flags & NL80211_RRF_DFS)
2288+ scnprintf(cac_time, sizeof(cac_time), "%u s",
2289+ reg_rule->dfs_cac_ms/1000);
2290+ else
2291+ scnprintf(cac_time, sizeof(cac_time), "N/A");
2292+
2293+
22762294 /*
22772295 * There may not be documentation for max antenna gain
22782296 * in certain regions
22792297 */
22802298 if (power_rule->max_antenna_gain)
2281− pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
2299+ pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
22822300 freq_range->start_freq_khz,
22832301 freq_range->end_freq_khz,
22842302 bw,
22852303 power_rule->max_antenna_gain,
2286− power_rule->max_eirp);
2304+ power_rule->max_eirp,
2305+ cac_time);
22872306 else
2288− pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
2307+ pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
22892308 freq_range->start_freq_khz,
22902309 freq_range->end_freq_khz,
22912310 bw,
2292− power_rule->max_eirp);
2311+ power_rule->max_eirp,
2312+ cac_time);
22932313 }
22942314 }
22952315