* [PATCH v3 1/4] cfg80211: add reg_get_dfs_region()
@ 2013-11-25 19:56 Janusz Dziedzic
2013-11-25 19:56 ` [PATCH v3 2/4] cfg80211: DFS check dfs_region before usage Janusz Dziedzic
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Janusz Dziedzic @ 2013-11-25 19:56 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, Luis R. Rodriguez
From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
This can be used outside of the regulatory context for any checks
on the DFS region. The central cfg80211 dfs_region is always used
and if it does not match with the wiphy a debug print is issued.
Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
---
net/wireless/reg.c | 27 +++++++++++++++++++++++++++
net/wireless/reg.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index ec54e1a..7d20d84 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -135,6 +135,33 @@ static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
return "Unknown";
}
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
+{
+ const struct ieee80211_regdomain *regd = NULL;
+ const struct ieee80211_regdomain *wiphy_regd = NULL;
+
+ regd = get_cfg80211_regdom();
+ if (!wiphy)
+ goto out;
+
+ wiphy_regd = get_wiphy_regdom(wiphy);
+ if (!wiphy_regd)
+ goto out;
+
+ if (wiphy_regd->dfs_region == regd->dfs_region)
+ goto out;
+
+ REG_DBG_PRINT("%s: device specific dfs_region "
+ "(%s) disagrees with cfg80211's "
+ "central dfs_region (%s)\n",
+ dev_name(&wiphy->dev),
+ reg_dfs_region_str(wiphy_regd->dfs_region),
+ reg_dfs_region_str(regd->dfs_region));
+
+out:
+ return regd->dfs_region;
+}
+
static void rcu_free_regdom(const struct ieee80211_regdomain *r)
{
if (!r)
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index cc4c2c0..02bd8f4 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -21,6 +21,7 @@ extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
bool reg_is_valid_request(const char *alpha2);
bool is_world_regdom(const char *alpha2);
bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
int regulatory_hint_user(const char *alpha2,
enum nl80211_user_reg_hint_type user_reg_hint_type);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v3 2/4] cfg80211: DFS check dfs_region before usage 2013-11-25 19:56 [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Janusz Dziedzic @ 2013-11-25 19:56 ` Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 3/4] cfg80211/mac80211: DFS pass CAC time as a parameter Janusz Dziedzic ` (2 subsequent siblings) 3 siblings, 0 replies; 10+ messages in thread From: Janusz Dziedzic @ 2013-11-25 19:56 UTC (permalink / raw) To: linux-wireless; +Cc: johannes, Luis R. Rodriguez, Janusz Dziedzic From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> Check the DFS region before channel availability check. Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com> Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> --- net/wireless/nl80211.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 70290f8..81579ae 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5650,8 +5650,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_chan_def chandef; + enum nl80211_dfs_regions dfs_region; int err; + dfs_region = reg_get_dfs_region(wdev->wiphy); + if (dfs_region == NL80211_DFS_UNSET) + return -EINVAL; + err = nl80211_parse_chandef(rdev, info, &chandef); if (err) return err; -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/4] cfg80211/mac80211: DFS pass CAC time as a parameter 2013-11-25 19:56 [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 2/4] cfg80211: DFS check dfs_region before usage Janusz Dziedzic @ 2013-11-25 19:56 ` Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels Janusz Dziedzic 2013-12-03 12:54 ` [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Johannes Berg 3 siblings, 0 replies; 10+ messages in thread From: Janusz Dziedzic @ 2013-11-25 19:56 UTC (permalink / raw) To: linux-wireless; +Cc: johannes, Janusz Dziedzic Send Channel Availability Check time as a parameter of start_radar_detection() callback. We could have different CAC time configuration for Off-channel CAC and for weather channels. Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> --- include/net/cfg80211.h | 3 ++- net/mac80211/cfg.c | 8 ++++---- net/wireless/nl80211.c | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6c2bc32..ce6bf12 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2434,7 +2434,8 @@ struct cfg80211_ops { int (*start_radar_detection)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_chan_def *chandef); + struct cfg80211_chan_def *chandef, + u32 cac_time_ms); int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie); int (*crit_proto_start)(struct wiphy *wiphy, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 267d3ac..5d69538 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2893,11 +2893,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, static int ieee80211_start_radar_detection(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_chan_def *chandef) + struct cfg80211_chan_def *chandef, + u32 cac_time_ms) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - unsigned long timeout; int err; if (!list_empty(&local->roc_list) || local->scanning) @@ -2915,9 +2915,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, if (err) return err; - timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); ieee80211_queue_delayed_work(&sdata->local->hw, - &sdata->dfs_cac_timer_work, timeout); + &sdata->dfs_cac_timer_work, + msecs_to_jiffies(cac_time_ms)); return 0; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 81579ae..b705640 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5686,7 +5686,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, if (err) return err; - err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); + err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef, + IEEE80211_DFS_MIN_CAC_TIME_MS); if (!err) { wdev->channel = chandef.chan; wdev->cac_started = true; -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels 2013-11-25 19:56 [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 2/4] cfg80211: DFS check dfs_region before usage Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 3/4] cfg80211/mac80211: DFS pass CAC time as a parameter Janusz Dziedzic @ 2013-11-25 19:56 ` Janusz Dziedzic 2013-11-26 14:50 ` Simon Wunderlich 2013-12-03 12:54 ` [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Johannes Berg 3 siblings, 1 reply; 10+ messages in thread From: Janusz Dziedzic @ 2013-11-25 19:56 UTC (permalink / raw) To: linux-wireless; +Cc: johannes, Janusz Dziedzic When nominal bandwidth falls completely or partly within the band 5600MHz to 5650MHz the CAC time shall be 10 minutes. This is ETSI requirement. FCC forbids weather channels usage. Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> --- include/net/cfg80211.h | 7 ++++- net/wireless/chan.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/core.h | 4 +++ net/wireless/mlme.c | 2 +- net/wireless/nl80211.c | 7 ++++- 5 files changed, 91 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ce6bf12..027c907 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -125,9 +125,12 @@ enum ieee80211_channel_flags { #define IEEE80211_CHAN_NO_HT40 \ (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) -#define IEEE80211_DFS_MIN_CAC_TIME_MS 60000 +#define IEEE80211_DFS_MIN_CAC_TIME_MS (60 * 1000) #define IEEE80211_DFS_MIN_NOP_TIME_MS (30 * 60 * 1000) +/* ETSI EN 301 893 V1.7.0 - Table D.1 */ +#define IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS (10 * 60 * 1000) + /** * struct ieee80211_channel - channel definition * @@ -3061,6 +3064,7 @@ struct cfg80211_cached_keys; * @p2p_started: true if this is a P2P Device that has been started * @cac_started: true if DFS channel availability check has been started * @cac_start_time: timestamp (jiffies) when the dfs state was entered. + * @cac_time_ms: CAC time in ms * @ps: powersave mode is enabled * @ps_timeout: dynamic powersave timeout * @ap_unexpected_nlportid: (private) netlink port ID of application @@ -3118,6 +3122,7 @@ struct wireless_dev { bool cac_started; unsigned long cac_start_time; + unsigned int cac_time_ms; #ifdef CONFIG_CFG80211_WEXT /* wext data */ diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 78559b5..680f469 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -490,6 +490,80 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, return r; } +static int cfg80211_get_chans_dfs_is_weather(struct wiphy *wiphy, + u32 center_freq, + u32 bandwidth) +{ + struct ieee80211_channel *c; + u32 start_freq, end_freq, freq; + + start_freq = cfg80211_get_start_freq(center_freq, bandwidth); + end_freq = cfg80211_get_end_freq(center_freq, bandwidth); + + /* + * ETSI EN 301 893 V1.7.0 Table D.1 + * 5600 - 5650MHz - weather radar channels + */ + for (freq = start_freq; freq <= end_freq; freq += 20) { + c = ieee80211_get_channel(wiphy, freq); + if (!c) + return -EINVAL; + if (c->center_freq >= 5600 && c->center_freq <= 5650) + return 1; + } + return 0; +} + +static int +cfg80211_chandef_dfs_is_weather(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef) +{ + int width; + int r; + + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return -EINVAL; + + width = cfg80211_chandef_get_width(chandef); + if (width < 0) + return -EINVAL; + + r = cfg80211_get_chans_dfs_is_weather(wiphy, chandef->center_freq1, + width); + + if (r) + return r; + + if (!chandef->center_freq2) + return 0; + + return cfg80211_get_chans_dfs_is_weather(wiphy, chandef->center_freq2, + width); +} + +unsigned int +cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + enum nl80211_dfs_regions dfs_region) +{ + unsigned int timeout_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; + + switch (dfs_region) { + case NL80211_DFS_ETSI: + if (cfg80211_chandef_dfs_is_weather(wiphy, chandef) > 0) + timeout_ms = IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS; + break; + /* TODO check JP CAC time */ + case NL80211_DFS_JP: + break; + /* FCC don't allow weather channels */ + case NL80211_DFS_FCC: + default: + break; + } + + return timeout_ms; +} static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, u32 center_freq, u32 bandwidth, diff --git a/net/wireless/core.h b/net/wireless/core.h index 0a277c3..88d9d0f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -400,6 +400,10 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, void cfg80211_dfs_channels_update_work(struct work_struct *work); +unsigned int +cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + enum nl80211_dfs_regions dfs_region); static inline int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 52cca05..6601e81 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev, switch (event) { case NL80211_RADAR_CAC_FINISHED: timeout = wdev->cac_start_time + - msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); + msecs_to_jiffies(wdev->cac_time_ms); WARN_ON(!time_after_eq(jiffies, timeout)); cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); break; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b705640..94fea18 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5651,6 +5651,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_chan_def chandef; enum nl80211_dfs_regions dfs_region; + unsigned int cac_time_ms; int err; dfs_region = reg_get_dfs_region(wdev->wiphy); @@ -5686,12 +5687,16 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, if (err) return err; + cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef, + dfs_region); + err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef, - IEEE80211_DFS_MIN_CAC_TIME_MS); + cac_time_ms); if (!err) { wdev->channel = chandef.chan; wdev->cac_started = true; wdev->cac_start_time = jiffies; + wdev->cac_time_ms = cac_time_ms; } return err; } -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels 2013-11-25 19:56 ` [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels Janusz Dziedzic @ 2013-11-26 14:50 ` Simon Wunderlich 2013-11-26 20:19 ` Janusz Dziedzic 0 siblings, 1 reply; 10+ messages in thread From: Simon Wunderlich @ 2013-11-26 14:50 UTC (permalink / raw) To: Janusz Dziedzic; +Cc: linux-wireless, johannes > When nominal bandwidth falls completely or partly > within the band 5600MHz to 5650MHz the CAC time shall > be 10 minutes. > This is ETSI requirement. FCC forbids weather channels usage. Although it is correct to handle that with longer times and all, I don't think we should enable weather channels at all, not even for ETSI. Unlike "normal" channels, it requires 99.99% detection rate in CAC, which is (I think) practically impossible. I guess we need ath9k (or other drivers, maybe ath10k too) to disallow CAC on these channels, if we know that the drivers can do it? Although I don't think it's technically possible ... Cheers, Simon ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels 2013-11-26 14:50 ` Simon Wunderlich @ 2013-11-26 20:19 ` Janusz Dziedzic 2013-11-26 20:39 ` Johannes Berg 0 siblings, 1 reply; 10+ messages in thread From: Janusz Dziedzic @ 2013-11-26 20:19 UTC (permalink / raw) To: Simon Wunderlich; +Cc: Janusz Dziedzic, linux-wireless, Johannes Berg 2013/11/26 Simon Wunderlich <sw@simonwunderlich.de>: > >> When nominal bandwidth falls completely or partly >> within the band 5600MHz to 5650MHz the CAC time shall >> be 10 minutes. >> This is ETSI requirement. FCC forbids weather channels usage. > > Although it is correct to handle that with longer times and all, I don't think > we should enable weather channels at all, not even for ETSI. Unlike "normal" > channels, it requires 99.99% detection rate in CAC, which is (I think) > practically impossible. > > I guess we need ath9k (or other drivers, maybe ath10k too) to disallow CAC on > these channels, if we know that the drivers can do it? Although I don't think > it's technically possible ... > ath.ko already disable weather channels by default. But in case driver will pass DFS certification (meet all requirements) - why not use weather channels? BR Janusz ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels 2013-11-26 20:19 ` Janusz Dziedzic @ 2013-11-26 20:39 ` Johannes Berg 2013-11-27 6:16 ` Janusz Dziedzic 0 siblings, 1 reply; 10+ messages in thread From: Johannes Berg @ 2013-11-26 20:39 UTC (permalink / raw) To: Janusz Dziedzic; +Cc: Simon Wunderlich, Janusz Dziedzic, linux-wireless On Tue, 2013-11-26 at 21:19 +0100, Janusz Dziedzic wrote: > ath.ko already disable weather channels by default. > But in case driver will pass DFS certification (meet all requirements) > - why not use weather channels? Since I'm a lazy bastard - can you demonstrate such a driver? I'm guessing not (immediately), so I'll drop your patches for now - maybe better to go back to the drawing board and get all of this into regdb etc. Doesn't seem critical to get it into the kernel now, if nobody really supports it anyway ... johannes ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels 2013-11-26 20:39 ` Johannes Berg @ 2013-11-27 6:16 ` Janusz Dziedzic 2013-12-02 14:43 ` Johannes Berg 0 siblings, 1 reply; 10+ messages in thread From: Janusz Dziedzic @ 2013-11-27 6:16 UTC (permalink / raw) To: Johannes Berg; +Cc: Simon Wunderlich, Janusz Dziedzic, linux-wireless 2013/11/26 Johannes Berg <johannes@sipsolutions.net>: > On Tue, 2013-11-26 at 21:19 +0100, Janusz Dziedzic wrote: > >> ath.ko already disable weather channels by default. >> But in case driver will pass DFS certification (meet all requirements) >> - why not use weather channels? > > Since I'm a lazy bastard - can you demonstrate such a driver? I'm > guessing not (immediately), so I'll drop your patches for now - maybe > better to go back to the drawing board and get all of this into regdb > etc. Doesn't seem critical to get it into the kernel now, if nobody > really supports it anyway ... > I could say something more after DFS tests. What about patch 1 and 2? BR Janusz ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels 2013-11-27 6:16 ` Janusz Dziedzic @ 2013-12-02 14:43 ` Johannes Berg 0 siblings, 0 replies; 10+ messages in thread From: Johannes Berg @ 2013-12-02 14:43 UTC (permalink / raw) To: Janusz Dziedzic; +Cc: Simon Wunderlich, Janusz Dziedzic, linux-wireless On Wed, 2013-11-27 at 07:16 +0100, Janusz Dziedzic wrote: > What about patch 1 and 2? I guess those still make sense as is. johannes ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() 2013-11-25 19:56 [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Janusz Dziedzic ` (2 preceding siblings ...) 2013-11-25 19:56 ` [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels Janusz Dziedzic @ 2013-12-03 12:54 ` Johannes Berg 3 siblings, 0 replies; 10+ messages in thread From: Johannes Berg @ 2013-12-03 12:54 UTC (permalink / raw) To: Janusz Dziedzic; +Cc: linux-wireless, Luis R. Rodriguez On Mon, 2013-11-25 at 20:56 +0100, Janusz Dziedzic wrote: > From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> > > This can be used outside of the regulatory context for any checks > on the DFS region. The central cfg80211 dfs_region is always used > and if it does not match with the wiphy a debug print is issued. Ok I've applied patches 1 and 2 johannes ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-12-03 12:54 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-11-25 19:56 [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 2/4] cfg80211: DFS check dfs_region before usage Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 3/4] cfg80211/mac80211: DFS pass CAC time as a parameter Janusz Dziedzic 2013-11-25 19:56 ` [PATCH v3 4/4] cfg80211: DFS use 10 minutes CAC when weather channels Janusz Dziedzic 2013-11-26 14:50 ` Simon Wunderlich 2013-11-26 20:19 ` Janusz Dziedzic 2013-11-26 20:39 ` Johannes Berg 2013-11-27 6:16 ` Janusz Dziedzic 2013-12-02 14:43 ` Johannes Berg 2013-12-03 12:54 ` [PATCH v3 1/4] cfg80211: add reg_get_dfs_region() Johannes Berg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox