* [PATCH v2 0/3] mac80211 client U-APSD support
@ 2009-11-30 13:24 Kalle Valo
2009-11-30 13:24 ` [PATCH v2 1/3] mac80211: add U-APSD client support Kalle Valo
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Kalle Valo @ 2009-11-30 13:24 UTC (permalink / raw)
To: linux-wireless
Hello,
here is my suggestion how to add U-APSD client support to mac80211. I
also included example driver implementation for wl1251.
Most probably I will drop patch 1 and fold patches 2 and 3, but I keep
them all in for now to make it easier to change things.
Please comment. Also I would like to get comments how U-APSD needs to
be implemented in different hardware.
v2:
o remove cfg80211 changes
o rename IEEE80211_QOS_IE to IEEE80211_WMM_IE_STA in ieee80211.h
---
Kalle Valo (3):
mac80211: add U-APSD client support
mac80211: add debugfs interface for U-APSD queue configuration
wl1251: add U-APSD support
drivers/net/wireless/wl12xx/wl1251_main.c | 12 ++++++--
include/linux/ieee80211.h | 5 ++++
include/net/mac80211.h | 6 ++++
net/mac80211/cfg.c | 7 +++++
net/mac80211/debugfs.c | 41 +++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 5 ++++
net/mac80211/main.c | 1 +
net/mac80211/mlme.c | 36 ++++++++++++++++++++++---
net/mac80211/scan.c | 18 +++++++++++++
net/mac80211/util.c | 2 +
10 files changed, 125 insertions(+), 8 deletions(-)
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/3] mac80211: add U-APSD client support
2009-11-30 13:24 [PATCH v2 0/3] mac80211 client U-APSD support Kalle Valo
@ 2009-11-30 13:24 ` Kalle Valo
2009-11-30 13:24 ` [PATCH v2 2/3] mac80211: add debugfs interface for U-APSD queue configuration Kalle Valo
2009-11-30 13:24 ` [PATCH v2 3/3] wl1251: add U-APSD support Kalle Valo
2 siblings, 0 replies; 4+ messages in thread
From: Kalle Valo @ 2009-11-30 13:24 UTC (permalink / raw)
To: linux-wireless
From: Kalle Valo <kalle.valo@nokia.com>
Add Unscheduled Automatic Power-Save Delivery (U-APSD) client support. The
idea is that the data frames from the client trigger AP to send the buffered
frames with ACs which have U-APSD enabled. This decreases latency and makes it
possible to save even more power.
Driver needs to use IEEE80211_HW_UAPSD to enable the feature. The current
implementation assumes that firmware takes care of the wakeup and
hardware needing IEEE80211_HW_PS_NULLFUNC_STACK is not yet supported.
Tested with wl1251 and Cisco Aironet 1200 AP.
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
---
include/linux/ieee80211.h | 5 +++++
include/net/mac80211.h | 6 ++++++
net/mac80211/cfg.c | 7 +++++++
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/mlme.c | 40 +++++++++++++++++++++++++++++++++++-----
net/mac80211/scan.c | 18 ++++++++++++++++++
net/mac80211/util.c | 2 ++
7 files changed, 75 insertions(+), 5 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index d9724a2..0153f3f 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -120,6 +120,11 @@
#define IEEE80211_QOS_CTL_TID_MASK 0x000F
#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
+#define IEEE80211_WMM_IE_STA_AC_VO (1<<0)
+#define IEEE80211_WMM_IE_STA_AC_VI (1<<1)
+#define IEEE80211_WMM_IE_STA_AC_BK (1<<2)
+#define IEEE80211_WMM_IE_STA_AC_BE (1<<3)
+
struct ieee80211_hdr {
__le16 frame_control;
__le16 duration_id;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1d75b96..2e484bc 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -113,6 +113,7 @@ struct ieee80211_tx_queue_params {
u16 cw_min;
u16 cw_max;
u8 aifs;
+ bool uapsd;
};
/**
@@ -928,6 +929,10 @@ enum ieee80211_tkip_key_type {
* @IEEE80211_HW_BEACON_FILTER:
* Hardware supports dropping of irrelevant beacon frames to
* avoid waking up cpu.
+ *
+ * @IEEE80211_HW_UAPSD:
+ * Hardware supports Unscheduled Automatic Power Save Delivery
+ * (U-APSD).
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -945,6 +950,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
IEEE80211_HW_MFP_CAPABLE = 1<<13,
IEEE80211_HW_BEACON_FILTER = 1<<14,
+ IEEE80211_HW_UAPSD = 1<<15,
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 93ee1fd..fd17958 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1134,6 +1134,13 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
p.cw_max = params->cwmax;
p.cw_min = params->cwmin;
p.txop = params->txop;
+
+ /*
+ * Setting tx queue params disables u-apsd because it's only
+ * called in master mode.
+ */
+ p.uapsd = false;
+
if (drv_conf_tx(local, params->queue, &p)) {
printk(KERN_DEBUG "%s: failed to set TX queue "
"parameters for queue %d\n",
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 785df97..94eaf21 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -81,6 +81,7 @@ struct ieee80211_bss {
u8 dtim_period;
bool wmm_used;
+ bool uapsd_supported;
unsigned long last_probe_resp;
@@ -264,6 +265,7 @@ enum ieee80211_sta_flags {
IEEE80211_STA_DISABLE_11N = BIT(4),
IEEE80211_STA_CSA_RECEIVED = BIT(5),
IEEE80211_STA_MFP_ENABLED = BIT(6),
+ IEEE80211_STA_UAPSD_ENABLED = BIT(7),
};
/* flags for MLME request */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6dc7b5a..e13a74d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -82,6 +82,8 @@ enum rx_mgmt_action {
RX_MGMT_CFG80211_ASSOC_TO,
};
+#define IEEE80211_DEFAULT_UAPSD_QUEUES IEEE80211_WMM_IE_STA_AC_VO
+
/* utils */
static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
{
@@ -235,13 +237,14 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- u8 *pos;
+ u8 *pos, qos_info;
const u8 *ies, *ht_ie;
int i, len, count, rates_len, supp_rates_len;
u16 capab;
int wmm = 0;
struct ieee80211_supported_band *sband;
u32 rates = 0;
+ bool uapsd;
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
sizeof(*mgmt) + 200 + wk->ie_len +
@@ -268,6 +271,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
capab |= WLAN_CAPABILITY_PRIVACY;
if (wk->bss->wmm_used)
wmm = 1;
+ uapsd = wk->bss->uapsd_supported;
/* get all rates supported by the device and the AP as
* some APs don't like getting a superset of their rates
@@ -368,6 +372,15 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
}
if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
+ if (uapsd && (local->hw.flags & IEEE80211_HW_UAPSD)) {
+ /* FIXME: configure queues from debugfs */
+ qos_info = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
+ } else {
+ qos_info = 0;
+ ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
+ }
+
pos = skb_put(skb, 9);
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 7; /* len */
@@ -377,7 +390,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
*pos++ = 2; /* WME */
*pos++ = 0; /* WME info */
*pos++ = 1; /* WME ver */
- *pos++ = 0;
+ *pos++ = qos_info; /* QoS info */
}
/* wmm support is a must to HT */
@@ -786,7 +799,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
struct ieee80211_tx_queue_params params;
size_t left;
int count;
- u8 *pos;
+ u8 *pos, uapsd_queues = 0;
if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
return;
@@ -796,6 +809,11 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
return;
+
+ if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
+ /* FIXME: use debugfs */
+ uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+
count = wmm_param[6] & 0x0f;
if (count == ifmgd->wmm_last_param_set)
return;
@@ -810,6 +828,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
for (; left >= 4; left -= 4, pos += 4) {
int aci = (pos[0] >> 5) & 0x03;
int acm = (pos[0] >> 4) & 0x01;
+ bool uapsd = false;
int queue;
switch (aci) {
@@ -817,22 +836,30 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
queue = 3;
if (acm)
local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
+ if (uapsd_queues & IEEE80211_WMM_IE_STA_AC_BK)
+ uapsd = true;
break;
case 2: /* AC_VI */
queue = 1;
if (acm)
local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
+ if (uapsd_queues & IEEE80211_WMM_IE_STA_AC_VI)
+ uapsd = true;
break;
case 3: /* AC_VO */
queue = 0;
if (acm)
local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
+ if (uapsd_queues & IEEE80211_WMM_IE_STA_AC_VO)
+ uapsd = true;
break;
case 0: /* AC_BE */
default:
queue = 2;
if (acm)
local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
+ if (uapsd_queues & IEEE80211_WMM_IE_STA_AC_BE)
+ uapsd = true;
break;
}
@@ -840,11 +867,14 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
params.cw_min = ecw2cw(pos[1] & 0x0f);
params.txop = get_unaligned_le16(pos + 2);
+ params.uapsd = uapsd;
+
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
- "cWmin=%d cWmax=%d txop=%d\n",
+ "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
wiphy_name(local->hw.wiphy), queue, aci, acm,
- params.aifs, params.cw_min, params.cw_max, params.txop);
+ params.aifs, params.cw_min, params.cw_max, params.txop,
+ params.uapsd);
#endif
if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx)
printk(KERN_DEBUG "%s: failed to set TX queue "
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 4cf387c..b11ae49 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -50,6 +50,23 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local,
cfg80211_put_bss((struct cfg80211_bss *)bss);
}
+static bool is_uapsd_supported(struct ieee802_11_elems *elems)
+{
+ u8 qos_info;
+
+ if (elems->wmm_info && elems->wmm_info_len == 7
+ && elems->wmm_info[5] == 1)
+ qos_info = elems->wmm_info[6];
+ else if (elems->wmm_param && elems->wmm_param_len == 24
+ && elems->wmm_param[5] == 1)
+ qos_info = elems->wmm_param[6];
+ else
+ /* no valid wmm information or parameter element found */
+ return false;
+
+ return qos_info & 0x80;
+}
+
struct ieee80211_bss *
ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status,
@@ -111,6 +128,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
}
bss->wmm_used = elems->wmm_param || elems->wmm_info;
+ bss->uapsd_supported = is_uapsd_supported(elems);
if (!beacon)
bss->last_probe_resp = jiffies;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d09f78b..7129b39 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -781,6 +781,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
break;
}
+ qparam.uapsd = false;
+
drv_conf_tx(local, queue, &qparam);
}
}
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] mac80211: add debugfs interface for U-APSD queue configuration
2009-11-30 13:24 [PATCH v2 0/3] mac80211 client U-APSD support Kalle Valo
2009-11-30 13:24 ` [PATCH v2 1/3] mac80211: add U-APSD client support Kalle Valo
@ 2009-11-30 13:24 ` Kalle Valo
2009-11-30 13:24 ` [PATCH v2 3/3] wl1251: add U-APSD support Kalle Valo
2 siblings, 0 replies; 4+ messages in thread
From: Kalle Valo @ 2009-11-30 13:24 UTC (permalink / raw)
To: linux-wireless
From: Kalle Valo <kalle.valo@nokia.com>
Because it's not yet decided how to configure which queues are U-APSD
enabled, add a debugfs interface for testing purposes.
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
---
net/mac80211/debugfs.c | 41 +++++++++++++++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 3 +++
net/mac80211/main.c | 1 +
net/mac80211/mlme.c | 8 ++------
4 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index e4b5409..780face 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -158,6 +158,47 @@ static const struct file_operations noack_ops = {
.open = mac80211_open_file_generic
};
+static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ int res;
+ char buf[10];
+
+ res = scnprintf(buf, sizeof(buf), "%d\n", local->uapsd_queues);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+}
+
+static ssize_t uapsd_queues_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ unsigned long val;
+ char buf[10];
+ size_t len;
+ int ret;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ ret = strict_strtoul(buf, 10, &val);
+
+ if (ret == 0)
+ local->uapsd_queues = val;
+
+ return count;
+}
+
+static const struct file_operations uapsd_queues_ops = {
+ .read = uapsd_queues_read,
+ .write = uapsd_queues_write,
+ .open = mac80211_open_file_generic
+};
+
static ssize_t queues_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 94eaf21..67c9756 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -58,6 +58,8 @@ struct ieee80211_local;
#define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024))
+#define IEEE80211_DEFAULT_UAPSD_QUEUES IEEE80211_WMM_IE_STA_AC_VO
+
struct ieee80211_fragment_entry {
unsigned long first_frag_time;
unsigned int seq;
@@ -746,6 +748,7 @@ struct ieee80211_local {
*/
int wifi_wme_noack_test;
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
+ unsigned int uapsd_queues;
bool pspolling;
/*
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index dd8ec8d..41b7cae 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -358,6 +358,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
local->user_power_level = -1;
+ local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
INIT_LIST_HEAD(&local->interfaces);
mutex_init(&local->iflist_mtx);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e13a74d..a25a461 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -82,8 +82,6 @@ enum rx_mgmt_action {
RX_MGMT_CFG80211_ASSOC_TO,
};
-#define IEEE80211_DEFAULT_UAPSD_QUEUES IEEE80211_WMM_IE_STA_AC_VO
-
/* utils */
static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
{
@@ -373,8 +371,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
if (uapsd && (local->hw.flags & IEEE80211_HW_UAPSD)) {
- /* FIXME: configure queues from debugfs */
- qos_info = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ qos_info = local->uapsd_queues;
ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
} else {
qos_info = 0;
@@ -811,8 +808,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
return;
if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
- /* FIXME: use debugfs */
- uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ uapsd_queues = local->uapsd_queues;
count = wmm_param[6] & 0x0f;
if (count == ifmgd->wmm_last_param_set)
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] wl1251: add U-APSD support
2009-11-30 13:24 [PATCH v2 0/3] mac80211 client U-APSD support Kalle Valo
2009-11-30 13:24 ` [PATCH v2 1/3] mac80211: add U-APSD client support Kalle Valo
2009-11-30 13:24 ` [PATCH v2 2/3] mac80211: add debugfs interface for U-APSD queue configuration Kalle Valo
@ 2009-11-30 13:24 ` Kalle Valo
2 siblings, 0 replies; 4+ messages in thread
From: Kalle Valo @ 2009-11-30 13:24 UTC (permalink / raw)
To: linux-wireless
From: Kalle Valo <kalle.valo@nokia.com>
wl1251 firmware supports U-APSD just with a simple queue configuration
change so enable it.
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
---
drivers/net/wireless/wl12xx/wl1251_main.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 6aeffbe..f35c012 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -1282,6 +1282,7 @@ static struct ieee80211_channel wl1251_channels[] = {
static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
+ enum wl1251_acx_ps_scheme ps_scheme;
struct wl1251 *wl = hw->priv;
int ret;
@@ -1299,10 +1300,14 @@ static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
if (ret < 0)
goto out_sleep;
+ if (params->uapsd)
+ ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER;
+ else
+ ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY;
+
ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue),
CHANNEL_TYPE_EDCF,
- wl1251_tx_get_queue(queue),
- WL1251_ACX_PS_SCHEME_LEGACY,
+ wl1251_tx_get_queue(queue), ps_scheme,
WL1251_ACX_ACK_POLICY_LEGACY);
if (ret < 0)
goto out_sleep;
@@ -1376,7 +1381,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM |
IEEE80211_HW_SUPPORTS_PS |
- IEEE80211_HW_BEACON_FILTER;
+ IEEE80211_HW_BEACON_FILTER |
+ IEEE80211_HW_UAPSD;
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
wl->hw->wiphy->max_scan_ssids = 1;
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-11-30 13:24 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-30 13:24 [PATCH v2 0/3] mac80211 client U-APSD support Kalle Valo
2009-11-30 13:24 ` [PATCH v2 1/3] mac80211: add U-APSD client support Kalle Valo
2009-11-30 13:24 ` [PATCH v2 2/3] mac80211: add debugfs interface for U-APSD queue configuration Kalle Valo
2009-11-30 13:24 ` [PATCH v2 3/3] wl1251: add U-APSD support Kalle Valo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).