From: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
To: shreyansh.jain@nxp.com
Cc: dev@dpdk.org, Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
Subject: [dpdk-dev] [PATCH] test/rawdev: add Multi-function test
Date: Mon, 16 Mar 2020 20:03:43 +0000 [thread overview]
Message-ID: <1584389023-32456-1-git-send-email-mairtin.oloingsigh@intel.com> (raw)
Function test for Multi-function library
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
app/test/Makefile | 5 +
app/test/test_cryptodev.h | 1 +
app/test/test_rawdev.c | 418 ++++++++++++++++++++++++++
app/test/test_rawdev_multi_fn_test_vectors.h | 83 +++++
4 files changed, 507 insertions(+), 0 deletions(-)
create mode 100644 app/test/test_rawdev_multi_fn_test_vectors.h
diff --git a/app/test/Makefile b/app/test/Makefile
index 1f080d1..57e9b23 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -243,6 +243,7 @@ CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
LDLIBS += -lm
+LDLIBS += -lrte_multi_fn
ifeq ($(CONFIG_RTE_LIBRTE_PDUMP),y)
LDLIBS += -lpthread
@@ -286,6 +287,10 @@ ifeq ($(CONFIG_RTE_APP_TEST_RESOURCE_TAR),y)
LDLIBS += -larchive
endif
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_AESNI_MB_RAWDEV),y)
+LDLIBS += -lrte_pmd_aesni_mb_rawdev
+endif
+
include $(RTE_SDK)/mk/rte.app.mk
endif
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index def304e..424184b 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -69,6 +69,7 @@
#define CRYPTODEV_NAME_OCTEONTX2_PMD crypto_octeontx2
#define CRYPTODEV_NAME_CAAM_JR_PMD crypto_caam_jr
#define CRYPTODEV_NAME_NITROX_PMD crypto_nitrox_sym
+#define RAWDEV_NAME_AESNI_MB_PMD rawdev_aesni_mb
/**
* Write (spread) data from buffer to mbuf data
diff --git a/app/test/test_rawdev.c b/app/test/test_rawdev.c
index 524a9d5..a1d03f9 100644
--- a/app/test/test_rawdev.c
+++ b/app/test/test_rawdev.c
@@ -6,10 +6,38 @@
#include <rte_malloc.h>
#include <rte_memcpy.h>
#include <rte_dev.h>
+#include <rte_crypto.h>
#include <rte_rawdev.h>
+#include <rte_multi_fn.h>
#include <rte_bus_vdev.h>
+#include "test_rawdev_multi_fn_test_vectors.h"
#include "test.h"
+#include "test_cryptodev.h"
+
+struct raw_testsuite_params {
+ struct rte_mempool *mbuf_pool;
+ struct rte_mempool *op_mpool;
+ struct rte_rawdev_info info;
+ struct rte_multi_fn_device_info priv;
+ struct rte_multi_fn_dev_config conf;
+ struct rte_multi_fn_qp_config qp_conf;
+ uint8_t valid_devs[RTE_RAWDEV_MAX_DEVS];
+ uint8_t valid_dev_count;
+};
+
+struct raw_unittest_params {
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_crypto_sym_xform auth_xform;
+ struct rte_crypto_sym_xform aead_xform;
+ struct rte_multi_fn_err_detect_xform err_detect;
+ struct rte_multi_fn_session *sess;
+
+ struct rte_crypto_op *op;
+ struct rte_mbuf *obuf, *ibuf;
+
+ uint8_t *digest;
+};
static int
test_rawdev_selftest_impl(const char *pmd, const char *opts)
@@ -45,3 +73,393 @@
}
REGISTER_TEST_COMMAND(ioat_rawdev_autotest, test_rawdev_selftest_ioat);
+
+static struct raw_testsuite_params testsuite_raw_params = { NULL };
+static struct raw_unittest_params unittest_raw_params;
+
+static int
+testsuite_raw_setup(void)
+{
+ int ret;
+ uint32_t i = 0, nb_devs, dev_id;
+ struct raw_testsuite_params *ts_params = &testsuite_raw_params;
+ struct rte_rawdev_info *info = &ts_params->info;
+ struct rte_multi_fn_device_info *priv = &ts_params->priv;
+
+ memset(ts_params, 0, sizeof(*ts_params));
+
+ info->dev_private = priv;
+ priv->config = &ts_params->conf;
+
+ ts_params->mbuf_pool = rte_mempool_lookup("RAWDEV_MBUFPOOL");
+ if (ts_params->mbuf_pool == NULL) {
+ /* Not already created so create */
+ ts_params->mbuf_pool = rte_pktmbuf_pool_create(
+ "RAWDEV_MBUFPOOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0, MBUF_SIZE,
+ rte_socket_id());
+ if (ts_params->mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create RAWDEV_MBUFPOOL\n");
+ return TEST_FAILED;
+ }
+ }
+
+ ts_params->op_mpool = rte_pktmbuf_pool_create("RAWDEV_MULTI_FN_OP_POOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0,
+ sizeof(struct rte_multi_fn_op) +
+ MAXIMUM_IV_LENGTH,
+ rte_socket_id());
+
+ if (ts_params->op_mpool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create RAWDEV_MULTI_FN_OP_POOL\n");
+ return TEST_FAILED;
+ }
+
+ /* Find 1st aesni rawdev. */
+ for (i = 0; i < RTE_RAWDEV_MAX_DEVS; i++)
+ if (rte_rawdevs[i].driver_name &&
+ (strncmp(rte_rawdevs[i].driver_name, "rawdev_aesni_mb",
+ RTE_RAWDEV_NAME_MAX_LEN) == 0))
+ break;
+
+ if (i == RTE_RAWDEV_MAX_DEVS)
+ rte_exit(EXIT_FAILURE, "Cannot find any ntb device.\n");
+
+ nb_devs = rte_rawdev_count();
+ if (nb_devs < 1) {
+ RTE_LOG(WARNING, USER1, "No rawdev devices found?\n");
+ return TEST_SKIPPED;
+ }
+
+ /* Create list of valid crypto devs */
+ for (i = 0; i < nb_devs; i++) {
+ rte_rawdev_info_get(i, info);
+ if (strncmp(rte_rawdevs[i].driver_name, "rawdev_aesni_mb",
+ RTE_RAWDEV_NAME_MAX_LEN) == 0)
+ ts_params->valid_devs[ts_params->valid_dev_count++]
+ = i;
+ }
+
+ if (ts_params->valid_dev_count < 1)
+ return TEST_FAILED;
+
+ /* Set up all the qps on the first of the valid devices found */
+
+ dev_id = ts_params->valid_devs[0];
+
+ ret = rte_rawdev_info_get(dev_id, info);
+ if (ret)
+ return ret;
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_raw_teardown(void)
+{
+ struct raw_testsuite_params *ts_params = &testsuite_raw_params;
+
+ if (ts_params->mbuf_pool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(ts_params->mbuf_pool));
+ rte_mempool_free(ts_params->mbuf_pool);
+ ts_params->mbuf_pool = NULL;
+ }
+
+ if (ts_params->op_mpool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_OP_POOL count %u\n",
+ rte_mempool_avail_count(ts_params->op_mpool));
+ rte_mempool_free(ts_params->op_mpool);
+ ts_params->op_mpool = NULL;
+ }
+
+ rte_vdev_uninit(RTE_STR(RAWDEV_NAME_AESNI_MB_PMD));
+}
+
+static int
+ut_raw_setup(void)
+{
+ int ret;
+ struct raw_testsuite_params *ts_params = &testsuite_raw_params;
+ struct raw_unittest_params *ut_params = &unittest_raw_params;
+
+ uint16_t qp_id;
+
+ /* Clear unit test parameters before running test */
+ memset(ut_params, 0, sizeof(*ut_params));
+
+ /* Reconfigure device to default parameters */
+ ts_params->qp_conf.nb_descriptors = MAX_NUM_OPS_INFLIGHT;
+
+ TEST_ASSERT_SUCCESS(rte_rawdev_configure(ts_params->valid_devs[0],
+ &ts_params->info),
+ "Failed to configure rawdev %u",
+ ts_params->valid_devs[0]);
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queues ; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_rawdev_queue_setup(
+ ts_params->valid_devs[0], qp_id,
+ &ts_params->qp_conf),
+ "Failed to setup queue pair %u on rawdev %u",
+ qp_id, ts_params->valid_devs[0]);
+ }
+
+ ret = rte_rawdev_xstats_reset(ts_params->valid_devs[0], NULL, 0);
+
+ TEST_ASSERT_SUCCESS(ret, "Failed to reset rawdev stats");
+
+ /* Start the device */
+ TEST_ASSERT_SUCCESS(rte_rawdev_start(ts_params->valid_devs[0]),
+ "Failed to start rawdev %u", ts_params->valid_devs[0]);
+
+ return 0;
+}
+
+static void
+ut_raw_teardown(void)
+{
+ struct raw_testsuite_params *ts_params = &testsuite_raw_params;
+ struct raw_unittest_params *ut_params = &unittest_raw_params;
+
+ /* free crypto operation structure */
+ if (ut_params->op)
+ rte_crypto_op_free(ut_params->op);
+
+ /*
+ * free mbuf - both obuf and ibuf are usually the same,
+ * so check if they point at the same address is necessary,
+ * to avoid freeing the mbuf twice.
+ */
+ if (ut_params->obuf) {
+ rte_pktmbuf_free(ut_params->obuf);
+ if (ut_params->ibuf == ut_params->obuf)
+ ut_params->ibuf = 0;
+ ut_params->obuf = 0;
+ }
+ if (ut_params->ibuf) {
+ rte_pktmbuf_free(ut_params->ibuf);
+ ut_params->ibuf = 0;
+ }
+
+ if (ts_params->mbuf_pool != NULL)
+ RTE_LOG(DEBUG, USER1, "CRYPTO_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(ts_params->mbuf_pool));
+
+ /* Stop the device */
+ rte_rawdev_stop(ts_params->valid_devs[0]);
+}
+
+static int
+test_session_create_docsis_dl(struct docsis_test_data *d_tc)
+{
+ uint16_t qpid = 0, enqueued, dequeued = 0;
+ uint16_t output_vec_len = 16;
+ struct rte_multi_fn_op *ops[2];
+ struct rte_multi_fn_op *results;
+ struct rte_multi_fn_xform xfrm1 = {0};
+ struct rte_multi_fn_xform xfrm2 = {0};
+ uint8_t *plaintext = NULL, *ciphertext = NULL;
+ struct rte_mbuf *m1, *m2;
+
+ /* Operations */
+ struct rte_crypto_sym_op *crypto_sym_op;
+ struct rte_multi_fn_err_detect_op *err_detect_op;
+ struct raw_testsuite_params *t_param = &testsuite_raw_params;
+ struct raw_unittest_params *u_param = &unittest_raw_params;
+
+ int i, ret = TEST_SUCCESS;
+ int oop = 0;
+
+ uint8_t key_128bit[16] = {0};
+ uint64_t stats[4] = {0};
+ const unsigned int stats_id[4] = {1, 2, 3, 4};
+ int num_stats = 0;
+
+ /* Docsis test params */
+ uint8_t *cipher_iv = NULL;
+ uint8_t cipher_iv_len = 0;
+ unsigned int cipher_len = 0, auth_len = 0;
+
+ uint8_t dev_id = t_param->valid_devs[0];
+
+ /* Copy key from test vector */
+ memcpy(key_128bit, d_tc->key.data, d_tc->key.len);
+
+ debug_hexdump(stdout, "Key:", key_128bit, d_tc->key.len);
+
+ /* multi-operation type session creation */
+ xfrm1.type = RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM;
+ xfrm1.next = &xfrm2;
+
+ xfrm1.crypto_sym.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+ struct rte_crypto_cipher_xform *xfrm_cipher = &xfrm1.crypto_sym.cipher;
+
+ xfrm_cipher->op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ xfrm_cipher->algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+ xfrm_cipher->key.data = key_128bit;
+ xfrm_cipher->key.length = RTE_DIM(key_128bit);
+ /*sizeof(key_128bit)/sizeof(key_128bit[0]);*/
+ xfrm_cipher->iv.offset = sizeof(struct rte_multi_fn_op);
+ xfrm_cipher->iv.length = d_tc->cipher_iv.len;
+
+ xfrm2.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+ xfrm2.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_CRC32_ETH;
+ xfrm2.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_VERIFY;
+ xfrm2.next = NULL;
+
+ m1 = rte_pktmbuf_alloc(t_param->mbuf_pool);
+ if (!m1) {
+ printf("rte_pktmbuf_alloc failed\n");
+ return -1;
+ }
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(m1, uint8_t *), 0, rte_pktmbuf_tailroom(m1));
+
+ if (oop) {
+ m2 = rte_pktmbuf_alloc(t_param->mbuf_pool);
+ rte_pktmbuf_append(m2, output_vec_len);
+ }
+
+ ciphertext = (uint8_t *)rte_pktmbuf_append(m1, d_tc->ciphertext.len);
+
+ memcpy(ciphertext, d_tc->ciphertext.data, d_tc->ciphertext.len);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, d_tc->ciphertext.len);
+
+ u_param->sess = rte_multi_fn_session_create(dev_id,
+ &t_param->info, &xfrm1, rte_socket_id());
+
+ if ((u_param->sess == NULL) ||
+ (u_param->sess->sess_private_data == NULL)) {
+ printf("rte_multi_fn_session_create create failed\n");
+ return -1;
+ }
+
+ /* Create combined DOCSIS operation */
+ cipher_iv = d_tc->cipher_iv.data;
+ cipher_iv_len = d_tc->cipher_iv.len;
+
+ cipher_len = d_tc->ciphertext.no_cipher == false ?
+ (d_tc->ciphertext.len -
+ d_tc->ciphertext.cipher_offset) :
+ 0;
+ auth_len = d_tc->ciphertext.no_auth == false ? (d_tc->ciphertext.len -
+ d_tc->ciphertext.auth_offset -
+ 4) : 0;
+
+ ret = rte_mempool_get_bulk(t_param->op_mpool, (void **)ops, 2);
+ if (ret) {
+ printf("rte_mempool_get_bulk failed to alloc ops\n");
+ return -1;
+ }
+
+ ops[0]->next = ops[1];
+ ops[0]->m_src = m1;
+ ops[0]->m_dst = NULL;
+
+ uint8_t *iv_ptr = (uint8_t *)ops[0] + sizeof(
+ struct rte_multi_fn_op);
+ rte_memcpy(iv_ptr, cipher_iv, cipher_iv_len);
+
+ debug_hexdump(stdout, "iv:", iv_ptr, cipher_iv_len);
+
+ /* crypto decrypt op config */
+ crypto_sym_op = &ops[0]->crypto_sym;
+ crypto_sym_op->cipher.data.offset = d_tc->ciphertext.cipher_offset;
+ crypto_sym_op->cipher.data.length = cipher_len;
+
+ /* error detect op config */
+ err_detect_op = &ops[1]->err_detect;
+ err_detect_op->data.offset = d_tc->ciphertext.auth_offset;
+ err_detect_op->data.length = auth_len;
+
+ /* Attach session to op */
+ ops[0]->sess = u_param->sess;
+
+ enqueued = rte_rawdev_enqueue_buffers(dev_id,
+ (struct rte_rawdev_buf **) ops, 1,
+ (rte_rawdev_obj_t)&qpid);
+
+ if (enqueued != 1)
+ printf("rte_accelerator_ops_enqueue failed\n");
+
+ do {
+ dequeued = rte_rawdev_dequeue_buffers(dev_id,
+ (struct rte_rawdev_buf **)&results, 1,
+ (rte_rawdev_obj_t)&qpid);
+ } while (dequeued < 1);
+
+ /* Check results. in-place operation */
+ plaintext = ciphertext;
+ debug_hexdump(stdout, "plaintext:", plaintext, d_tc->plaintext.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ plaintext,
+ d_tc->plaintext.data,
+ /* Check only plaintext, CRC is checked internally */
+ d_tc->plaintext.len - 4,
+ "DOCSIS Plaintext data not as expected");
+
+ TEST_ASSERT_EQUAL(results->op_status,
+ RTE_MULTI_FN_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ num_stats = rte_rawdev_xstats_get(dev_id, stats_id, stats, 4);
+ for (i = 0; i < num_stats; i++)
+ printf("Stat num: %d = %"PRIu64"\n", i, stats[i]);
+
+ ret = rte_multi_fn_session_destroy(dev_id, &t_param->info,
+ u_param->sess);
+
+ return ret;
+}
+
+static int
+test_device_configure_docsis_decrypt(void)
+{
+ return test_session_create_docsis_dl(&docsis_test_case_1);
+}
+
+static struct unit_test_suite rawdev_aesni_testsuite = {
+ .suite_name = "Raw Unit Test Suite",
+ .setup = testsuite_raw_setup,
+ .teardown = testsuite_raw_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_raw_setup, ut_raw_teardown,
+ test_device_configure_docsis_decrypt),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_rawdev_aesni(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ int i, ret;
+
+ ret = rte_vdev_init(RTE_STR(RAWDEV_NAME_AESNI_MB_PMD), NULL);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "aesni raw vdev init failed\n");
+ return ret;
+ }
+
+ /* Find 1st ntb rawdev. */
+ for (i = 0; i < RTE_RAWDEV_MAX_DEVS; i++)
+ if (rte_rawdevs[i].driver_name &&
+ (strncmp(rte_rawdevs[i].driver_name, "rawdev_aesni_mb",
+ RTE_RAWDEV_NAME_MAX_LEN) == 0) &&
+ (rte_rawdevs[i].attached == 1))
+ break;
+
+ if (i == RTE_RAWDEV_MAX_DEVS) {
+ RTE_LOG(ERR, USER1, "aesni raw driver needed to run test\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&rawdev_aesni_testsuite);
+}
+
+REGISTER_TEST_COMMAND(rawdev_aesni_autotest, test_rawdev_aesni);
+
diff --git a/app/test/test_rawdev_multi_fn_test_vectors.h b/app/test/test_rawdev_multi_fn_test_vectors.h
new file mode 100644
index 0000000..f60400d
--- /dev/null
+++ b/app/test/test_rawdev_multi_fn_test_vectors.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (C) 2015-2016 Freescale Semiconductor,Inc.
+ * Copyright 2018-2019 NXP
+ */
+
+#ifndef TEST_RAWDEV_MULTI_FN_TEST_VECTORS_H_
+#define TEST_RAWDEV_MULTI_FN_TEST_VECTORS_H_
+
+#include <stdbool.h>
+
+struct docsis_test_data {
+ struct {
+ uint8_t data[16];
+ unsigned int len;
+ } key;
+
+ struct {
+ uint8_t data[16] __rte_aligned(16);
+ unsigned int len;
+ } cipher_iv;
+
+ struct {
+ uint8_t data[1024];
+ unsigned int len;
+ unsigned int cipher_offset;
+ unsigned int auth_offset;
+ bool no_cipher;
+ bool no_auth;
+ } plaintext;
+
+ struct {
+ uint8_t data[1024];
+ unsigned int len;
+ unsigned int cipher_offset;
+ unsigned int auth_offset;
+ bool no_cipher;
+ bool no_auth;
+ } ciphertext;
+};
+
+struct docsis_test_data docsis_test_case_1 = {
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+ 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x06, 0x05, 0x04, 0x03,
+ 0x02, 0x01, 0x08, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
+ },
+ .len = 24,
+ .cipher_offset = 18,
+ .auth_offset = 6,
+ .no_cipher = false,
+ .no_auth = false
+ },
+ .ciphertext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x06, 0x05, 0x04, 0x03,
+ 0x02, 0x01, 0x7A, 0xF0, 0x61, 0xF8, 0x63, 0x42
+ },
+ .len = 24,
+ .cipher_offset = 18,
+ .auth_offset = 6,
+ .no_cipher = false,
+ .no_auth = false
+ }
+};
+
+#endif /* TEST_RAWDEV_MULTI_FN_TEST_VECTORS_H_ */
--
1.7.0.7
reply other threads:[~2020-03-16 20:03 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1584389023-32456-1-git-send-email-mairtin.oloingsigh@intel.com \
--to=mairtin.oloingsigh@intel.com \
--cc=dev@dpdk.org \
--cc=shreyansh.jain@nxp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).