From: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
To: dev@dpdk.org
Cc: Jay Ding <jay.ding@broadcom.com>,
Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>,
Michael Baucom <michael.baucom@broadcom.com>,
Ajit Khaparde <ajit.khaparde@broadcom.com>
Subject: [PATCH v6 34/47] net/bnxt: tf_ulp: add rte_mtr support for Thor2
Date: Mon, 21 Oct 2024 13:55:54 +0530 [thread overview]
Message-ID: <20241021082607.232829-35-sriharsha.basavapatna@broadcom.com> (raw)
In-Reply-To: <20241021082607.232829-1-sriharsha.basavapatna@broadcom.com>
From: Jay Ding <jay.ding@broadcom.com>
1. Implement Thor2 meter template tables
2. Add Thor2 meter support in ULP
3. Make rte_mtr API implementation device independent
to adapt Thor2 meter hw change
4. Fix the round issue in xir calculation
Signed-off-by: Jay Ding <jay.ding@broadcom.com>
Signed-off-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Reviewed-by: Michael Baucom <michael.baucom@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
drivers/net/bnxt/tf_ulp/bnxt_ulp.h | 12 +-
drivers/net/bnxt/tf_ulp/bnxt_ulp_meter.c | 273 +++++++----------------
drivers/net/bnxt/tf_ulp/bnxt_ulp_tf.c | 113 +++++++++-
drivers/net/bnxt/tf_ulp/bnxt_ulp_tfc.c | 47 +++-
drivers/net/bnxt/tf_ulp/ulp_rte_parser.c | 12 +-
5 files changed, 246 insertions(+), 211 deletions(-)
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
index d62a9df5f0..4868339478 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h
@@ -12,6 +12,7 @@
#include "rte_version.h"
#include "rte_ethdev.h"
+#include "rte_mtr.h"
#include "bnxt.h"
#include "ulp_template_db_enum.h"
@@ -231,6 +232,10 @@ struct bnxt_ulp_core_ops {
int32_t
(*ulp_vfr_session_fid_rem)(struct bnxt_ulp_context *ulp_ctx,
uint16_t rep_fid);
+
+ int32_t
+ (*ulp_mtr_cap_get)(struct bnxt *bp,
+ struct rte_mtr_capabilities *cap);
};
extern const struct bnxt_ulp_core_ops bnxt_ulp_tf_core_ops;
@@ -566,9 +571,6 @@ bnxt_ulp_cntxt_ecpri_udp_port_set(struct bnxt_ulp_context *ulp_ctx,
unsigned int
bnxt_ulp_cntxt_ecpri_udp_port_get(struct bnxt_ulp_context *ulp_ctx);
-int32_t
-bnxt_flow_meter_init(struct bnxt *bp);
-
uint32_t
bnxt_ulp_cntxt_convert_dev_id(uint32_t ulp_dev_id);
@@ -618,4 +620,8 @@ bnxt_ulp_vfr_session_fid_add(struct bnxt_ulp_context *ulp_ctx,
int32_t
bnxt_ulp_vfr_session_fid_rem(struct bnxt_ulp_context *ulp_ctx,
uint16_t vfr_fid);
+
+int32_t
+bnxt_flow_mtr_init(struct bnxt *bp __rte_unused);
+
#endif /* _BNXT_ULP_H_ */
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp_meter.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp_meter.c
index 61d006fc08..37b5cc4dfb 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp_meter.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp_meter.c
@@ -40,122 +40,24 @@
/**
* Meter init status
*/
-int bnxt_meter_initialized;
+int bnxt_mtr_initialized;
-/**
- * Internal api to config global config.
- * returns 0 on success.
- */
-static int32_t
-bnxt_meter_global_cfg_update(struct bnxt *bp,
- enum tf_dir dir,
- enum tf_global_config_type type,
- uint32_t offset,
- uint32_t value,
- uint32_t set_flag)
-{
- uint32_t global_cfg = 0;
- struct tf_global_cfg_parms parms = { 0 };
- struct tf *tfp;
- int32_t rc = 0;
-
- parms.dir = dir,
- parms.type = type,
- parms.offset = offset,
- parms.config = (uint8_t *)&global_cfg,
- parms.config_sz_in_bytes = sizeof(global_cfg);
-
- tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
- rc = tf_get_global_cfg(tfp, &parms);
- if (rc) {
- BNXT_DRV_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n",
- type, rc);
- return rc;
- }
-
- if (set_flag)
- global_cfg |= value;
- else
- global_cfg &= ~value;
-
- rc = tf_set_global_cfg(tfp, &parms);
- if (rc) {
- BNXT_DRV_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n",
- type, rc);
- return rc;
- }
- return rc;
-}
-
-/**
- * When a port is initialized by dpdk. This functions is called
- * to enable the meter and initializes the meter global configurations.
- */
-#define BNXT_THOR_FMTCR_NUM_MET_MET_1K (0x7UL << 20)
-#define BNXT_THOR_FMTCR_CNTRS_ENABLE (0x1UL << 25)
-#define BNXT_THOR_FMTCR_INTERVAL_1K (1024)
int32_t
-bnxt_flow_meter_init(struct bnxt *bp)
+bnxt_flow_mtr_init(struct bnxt *bp __rte_unused)
{
- int rc = 0;
-
- /*
- * Enable metering. Set the meter global configuration register.
- * Set number of meter to 1K. Disable the drop counter for now.
- */
- rc = bnxt_meter_global_cfg_update(bp, TF_DIR_RX, TF_METER_CFG,
- 0,
- BNXT_THOR_FMTCR_NUM_MET_MET_1K,
- 1);
- if (rc) {
- BNXT_DRV_DBG(ERR, "Failed to set rx meter configuration\n");
- goto jump_to_error;
- }
-
- rc = bnxt_meter_global_cfg_update(bp, TF_DIR_TX, TF_METER_CFG,
- 0,
- BNXT_THOR_FMTCR_NUM_MET_MET_1K,
- 1);
- if (rc) {
- BNXT_DRV_DBG(ERR, "Failed to set tx meter configuration\n");
- goto jump_to_error;
- }
-
/*
- * Set meter refresh rate to 1024 clock cycle. This value works for
- * most bit rates especially for high rates.
- */
- rc = bnxt_meter_global_cfg_update(bp, TF_DIR_RX, TF_METER_INTERVAL_CFG,
- 0,
- BNXT_THOR_FMTCR_INTERVAL_1K,
- 1);
- if (rc) {
- BNXT_DRV_DBG(ERR, "Failed to set rx meter interval\n");
- goto jump_to_error;
- }
-
- rc = bnxt_meter_global_cfg_update(bp, TF_DIR_TX, TF_METER_INTERVAL_CFG,
- 0,
- BNXT_THOR_FMTCR_INTERVAL_1K,
- 1);
- if (rc) {
- BNXT_DRV_DBG(ERR, "Failed to set tx meter interval\n");
- goto jump_to_error;
- }
-
- bnxt_meter_initialized = 1;
+ ** Enable metering. The meter refresh interval is set to 1K
+ ** in FW. The meters is set to drop packet and meter cache is
+ ** enabled by HW default.
+ **/
+ bnxt_mtr_initialized = 1;
BNXT_DRV_DBG(DEBUG, "Bnxt flow meter has been initialized\n");
- return rc;
-
-jump_to_error:
- return rc;
+ return 0;
}
/**
* Get meter capabilities.
*/
-#define MAX_FLOW_PER_METER 1024
-#define MAX_METER_RATE_100GBPS ((1ULL << 30) * 100 / 8)
static int
bnxt_flow_mtr_cap_get(struct rte_eth_dev *dev,
struct rte_mtr_capabilities *cap,
@@ -163,11 +65,9 @@ bnxt_flow_mtr_cap_get(struct rte_eth_dev *dev,
{
struct bnxt *bp = dev->data->dev_private;
uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
- struct tf_get_session_info_parms iparms;
- struct tf *tfp;
int32_t rc = 0;
- if (!bnxt_meter_initialized)
+ if (!bnxt_mtr_initialized)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
@@ -180,35 +80,12 @@ bnxt_flow_mtr_cap_get(struct rte_eth_dev *dev,
NULL,
"Unable to get device id from ulp");
- /* Get number of meter reserved for this session */
- memset(&iparms, 0, sizeof(iparms));
- tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
- rc = tf_get_session_info(tfp, &iparms);
- if (rc != 0)
+ rc = bp->ulp_ctx->ops->ulp_mtr_cap_get(bp, cap);
+ if (rc)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
- "Failed to get session resource info");
-
- memset(cap, 0, sizeof(struct rte_mtr_capabilities));
-
- cap->n_max = iparms.session_info.tbl[TF_DIR_RX].info[TF_TBL_TYPE_METER_INST].stride;
- if (!cap->n_max)
- return -rte_mtr_error_set(error, ENOTSUP,
- RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
- "Meter is not supported");
-
- cap->srtcm_rfc2697_byte_mode_supported = 1;
- cap->n_shared_max = cap->n_max;
- /* No meter is identical */
- cap->identical = 1;
- cap->shared_identical = 1;
- cap->shared_n_flows_per_mtr_max = MAX_FLOW_PER_METER;
- cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
- cap->meter_srtcm_rfc2697_n_max = cap->n_max;
- cap->meter_rate_max = MAX_METER_RATE_100GBPS;
- /* No stats supported now */
- cap->stats_mask = 0;
+ "Unable to get meter capabilities");
return 0;
}
@@ -218,9 +95,8 @@ bnxt_flow_mtr_cap_get(struct rte_eth_dev *dev,
*/
#define BNXT_CPU_CLOCK 800
#define MEGA 1000000
-#define NUM_BIT_PER_BYTE 8
static inline void
-bnxt_ulp_flow_meter_xir_calc(int64_t xir, uint32_t *reg)
+bnxt_ulp_flow_mtr_xir_calc(int64_t xir, uint32_t *reg)
{
int64_t temp;
uint16_t m = 0;
@@ -248,7 +124,7 @@ bnxt_ulp_flow_meter_xir_calc(int64_t xir, uint32_t *reg)
* = round(b*2^(38-e) - 2^11)
*
*/
- m = xir * (1 << (38 - e)) / BNXT_CPU_CLOCK / MEGA - (1 << 11);
+ m = (xir * (1 << (38 - e)) / BNXT_CPU_CLOCK / (MEGA / 10) + 5) / 10 - (1 << 11);
*reg = ((m & 0x7FF) << 6) | (e & 0x3F);
swap = (uint8_t *)reg;
*reg = swap[0] << 16 | swap[1] << 8 | swap[2];
@@ -258,7 +134,7 @@ bnxt_ulp_flow_meter_xir_calc(int64_t xir, uint32_t *reg)
* Calculate mantissa and exponent for cbs / ebs reg.
*/
static inline void
-bnxt_ulp_flow_meter_xbs_calc(int64_t xbs, uint16_t *reg)
+bnxt_ulp_flow_mtr_xbs_calc(int64_t xbs, uint16_t *reg)
{
uint16_t m = 0;
uint16_t e = 0;
@@ -288,7 +164,7 @@ bnxt_ulp_flow_meter_xbs_calc(int64_t xbs, uint16_t *reg)
* Parse the meter profile.
*/
static inline int
-bnxt_ulp_meter_profile_parse(struct ulp_rte_act_prop *act_prop,
+bnxt_ulp_mtr_profile_parse(struct ulp_rte_act_prop *act_prop,
const struct rte_mtr_meter_profile *profile,
struct rte_mtr_error *error)
{
@@ -357,22 +233,22 @@ bnxt_ulp_meter_profile_parse(struct ulp_rte_act_prop *act_prop,
NULL,
"PIR must be equal to or greater than CIR");
- bnxt_ulp_flow_meter_xir_calc(cir, &cir_reg);
+ bnxt_ulp_flow_mtr_xir_calc(cir, &cir_reg);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_CIR],
&cir_reg,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_CIR);
- bnxt_ulp_flow_meter_xir_calc(eir, &eir_reg);
+ bnxt_ulp_flow_mtr_xir_calc(eir, &eir_reg);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_EIR],
&eir_reg,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_EIR);
- bnxt_ulp_flow_meter_xbs_calc(cbs, &cbs_reg);
+ bnxt_ulp_flow_mtr_xbs_calc(cbs, &cbs_reg);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_CBS],
&cbs_reg,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_CBS);
- bnxt_ulp_flow_meter_xbs_calc(ebs, &ebs_reg);
+ bnxt_ulp_flow_mtr_xbs_calc(ebs, &ebs_reg);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_EBS],
&ebs_reg,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_EBS);
@@ -392,8 +268,8 @@ bnxt_ulp_meter_profile_parse(struct ulp_rte_act_prop *act_prop,
* Add MTR profile.
*/
static int
-bnxt_flow_meter_profile_add(struct rte_eth_dev *dev,
- uint32_t meter_profile_id,
+bnxt_flow_mtr_profile_add(struct rte_eth_dev *dev,
+ uint32_t mtr_profile_id,
struct rte_mtr_meter_profile *profile,
struct rte_mtr_error *error)
{
@@ -406,7 +282,7 @@ bnxt_flow_meter_profile_add(struct rte_eth_dev *dev,
int ret;
uint32_t tmp_profile_id;
- if (!bnxt_meter_initialized)
+ if (!bnxt_mtr_initialized)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
@@ -426,12 +302,12 @@ bnxt_flow_meter_profile_add(struct rte_eth_dev *dev,
/* not direction from rte_mtr. Set ingress by default */
params.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
- tmp_profile_id = tfp_cpu_to_be_32(meter_profile_id);
+ tmp_profile_id = tfp_cpu_to_be_32(mtr_profile_id);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_ID],
&tmp_profile_id,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_ID);
- ret = bnxt_ulp_meter_profile_parse(act_prop, profile, error);
+ ret = bnxt_ulp_mtr_profile_parse(act_prop, profile, error);
if (ret)
goto parse_error;
@@ -478,8 +354,8 @@ bnxt_flow_meter_profile_add(struct rte_eth_dev *dev,
* Delete meter profile.
*/
static int
-bnxt_flow_meter_profile_delete(struct rte_eth_dev *dev,
- uint32_t meter_profile_id,
+bnxt_flow_mtr_profile_delete(struct rte_eth_dev *dev,
+ uint32_t mtr_profile_id,
struct rte_mtr_error *error)
{
struct bnxt_ulp_context *ulp_ctx;
@@ -491,7 +367,7 @@ bnxt_flow_meter_profile_delete(struct rte_eth_dev *dev,
int ret;
uint32_t tmp_profile_id;
- if (!bnxt_meter_initialized)
+ if (!bnxt_mtr_initialized)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
@@ -512,7 +388,7 @@ bnxt_flow_meter_profile_delete(struct rte_eth_dev *dev,
/* not direction from rte_mtr. Set ingress by default */
params.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
- tmp_profile_id = tfp_cpu_to_be_32(meter_profile_id);
+ tmp_profile_id = tfp_cpu_to_be_32(mtr_profile_id);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_PROF_ID],
&tmp_profile_id,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_ID);
@@ -547,7 +423,7 @@ bnxt_flow_meter_profile_delete(struct rte_eth_dev *dev,
goto parse_error;
BNXT_DRV_DBG(DEBUG, "Bnxt flow meter profile %d deleted\n",
- meter_profile_id);
+ mtr_profile_id);
return 0;
@@ -562,7 +438,7 @@ bnxt_flow_meter_profile_delete(struct rte_eth_dev *dev,
* Create meter.
*/
static int
-bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
+bnxt_flow_mtr_create(struct rte_eth_dev *dev, uint32_t mtr_id,
struct rte_mtr_params *params, int shared __rte_unused,
struct rte_mtr_error *error)
{
@@ -572,11 +448,11 @@ bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
struct bnxt_ulp_mapper_parms mparms = { 0 };
uint32_t act_tid;
uint16_t func_id;
- bool meter_en = params->meter_enable ? true : false;
+ bool mtr_en = params->meter_enable ? true : false;
int ret;
- uint32_t tmp_meter_id, tmp_profile_id;
+ uint32_t tmp_mtr_id, tmp_profile_id;
- if (!bnxt_meter_initialized)
+ if (!bnxt_mtr_initialized)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
@@ -596,9 +472,9 @@ bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
/* not direction from rte_mtr. Set ingress by default */
pparams.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
- tmp_meter_id = tfp_cpu_to_be_32(meter_id);
+ tmp_mtr_id = tfp_cpu_to_be_32(mtr_id);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_ID],
- &tmp_meter_id,
+ &tmp_mtr_id,
BNXT_ULP_ACT_PROP_SZ_METER_INST_ID);
tmp_profile_id = tfp_cpu_to_be_32(params->meter_profile_id);
@@ -607,7 +483,7 @@ bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
BNXT_ULP_ACT_PROP_SZ_METER_PROF_ID);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_MTR_VAL],
- &meter_en,
+ &mtr_en,
BNXT_ULP_ACT_PROP_SZ_METER_INST_MTR_VAL);
ret = ulp_matcher_action_match(&pparams, &act_tid);
@@ -639,7 +515,7 @@ bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
if (ret)
goto parse_error;
- BNXT_DRV_DBG(DEBUG, "Bnxt flow meter %d is created\n", meter_id);
+ BNXT_DRV_DBG(DEBUG, "Bnxt flow meter %d is created\n", mtr_id);
return 0;
parse_error:
@@ -653,8 +529,8 @@ bnxt_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
* Destroy meter.
*/
static int
-bnxt_flow_meter_destroy(struct rte_eth_dev *dev,
- uint32_t meter_id,
+bnxt_flow_mtr_destroy(struct rte_eth_dev *dev,
+ uint32_t mtr_id,
struct rte_mtr_error *error)
{
struct bnxt_ulp_context *ulp_ctx;
@@ -664,9 +540,9 @@ bnxt_flow_meter_destroy(struct rte_eth_dev *dev,
uint32_t act_tid;
uint16_t func_id;
int ret;
- uint32_t tmp_meter_id;
+ uint32_t tmp_mtr_id;
- if (!bnxt_meter_initialized)
+ if (!bnxt_mtr_initialized)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
@@ -687,9 +563,9 @@ bnxt_flow_meter_destroy(struct rte_eth_dev *dev,
/* not direction from rte_mtr. Set ingress by default */
pparams.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
- tmp_meter_id = tfp_cpu_to_be_32(meter_id);
+ tmp_mtr_id = tfp_cpu_to_be_32(mtr_id);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_ID],
- &tmp_meter_id,
+ &tmp_mtr_id,
BNXT_ULP_ACT_PROP_SZ_METER_INST_ID);
ret = ulp_matcher_action_match(&pparams, &act_tid);
@@ -721,7 +597,7 @@ bnxt_flow_meter_destroy(struct rte_eth_dev *dev,
if (ret)
goto parse_error;
- BNXT_DRV_DBG(DEBUG, "Bnxt flow meter %d is deleted\n", meter_id);
+ BNXT_DRV_DBG(DEBUG, "Bnxt flow meter %d is deleted\n", mtr_id);
return 0;
parse_error:
@@ -735,8 +611,8 @@ bnxt_flow_meter_destroy(struct rte_eth_dev *dev,
* Set meter valid/invalid.
*/
static int
-bnxt_flow_meter_enable_set(struct rte_eth_dev *dev,
- uint32_t meter_id,
+bnxt_flow_mtr_enable_set(struct rte_eth_dev *dev,
+ uint32_t mtr_id,
uint8_t val,
struct rte_mtr_error *error)
{
@@ -747,9 +623,9 @@ bnxt_flow_meter_enable_set(struct rte_eth_dev *dev,
uint32_t act_tid;
uint16_t func_id;
int ret;
- uint32_t tmp_meter_id;
+ uint32_t tmp_mtr_id;
- if (!bnxt_meter_initialized)
+ if (!bnxt_mtr_initialized)
return -rte_mtr_error_set(error, ENOTSUP,
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
NULL,
@@ -770,9 +646,9 @@ bnxt_flow_meter_enable_set(struct rte_eth_dev *dev,
/* not direction from rte_mtr. Set ingress by default */
pparams.dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
- tmp_meter_id = tfp_cpu_to_be_32(meter_id);
+ tmp_mtr_id = tfp_cpu_to_be_32(mtr_id);
memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_ID],
- &tmp_meter_id,
+ &tmp_mtr_id,
BNXT_ULP_ACT_PROP_SZ_METER_INST_ID);
act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_MTR_VAL_UPDATE] = 1;
act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER_INST_MTR_VAL] = val;
@@ -807,7 +683,7 @@ bnxt_flow_meter_enable_set(struct rte_eth_dev *dev,
goto parse_error;
BNXT_DRV_DBG(DEBUG, "Bnxt flow meter %d is %s\n",
- meter_id, val ? "enabled" : "disabled");
+ mtr_id, val ? "enabled" : "disabled");
return 0;
parse_error:
@@ -821,31 +697,31 @@ bnxt_flow_meter_enable_set(struct rte_eth_dev *dev,
* Enable flow meter.
*/
static int
-bnxt_flow_meter_enable(struct rte_eth_dev *dev,
- uint32_t meter_id,
+bnxt_flow_mtr_enable(struct rte_eth_dev *dev,
+ uint32_t mtr_id,
struct rte_mtr_error *error)
{
- return bnxt_flow_meter_enable_set(dev, meter_id, 1, error);
+ return bnxt_flow_mtr_enable_set(dev, mtr_id, 1, error);
}
/**
* Disable flow meter.
*/
static int
-bnxt_flow_meter_disable(struct rte_eth_dev *dev,
- uint32_t meter_id,
+bnxt_flow_mtr_disable(struct rte_eth_dev *dev,
+ uint32_t mtr_id,
struct rte_mtr_error *error)
{
- return bnxt_flow_meter_enable_set(dev, meter_id, 0, error);
+ return bnxt_flow_mtr_enable_set(dev, mtr_id, 0, error);
}
/**
* Update meter profile.
*/
static int
-bnxt_flow_meter_profile_update(struct rte_eth_dev *dev __rte_unused,
- uint32_t meter_id __rte_unused,
- uint32_t meter_profile_id __rte_unused,
+bnxt_flow_mtr_profile_update(struct rte_eth_dev *dev __rte_unused,
+ uint32_t mtr_id __rte_unused,
+ uint32_t mtr_profile_id __rte_unused,
struct rte_mtr_error *error)
{
return -rte_mtr_error_set(error, ENOTSUP,
@@ -858,8 +734,8 @@ bnxt_flow_meter_profile_update(struct rte_eth_dev *dev __rte_unused,
* Udate meter stats mask.
*/
static int
-bnxt_flow_meter_stats_update(struct rte_eth_dev *dev __rte_unused,
- uint32_t meter_id __rte_unused,
+bnxt_flow_mtr_stats_update(struct rte_eth_dev *dev __rte_unused,
+ uint32_t mtr_id __rte_unused,
uint64_t stats_mask __rte_unused,
struct rte_mtr_error *error)
{
@@ -873,8 +749,8 @@ bnxt_flow_meter_stats_update(struct rte_eth_dev *dev __rte_unused,
* Read meter statistics.
*/
static int
-bnxt_flow_meter_stats_read(struct rte_eth_dev *dev __rte_unused,
- uint32_t meter_id __rte_unused,
+bnxt_flow_mtr_stats_read(struct rte_eth_dev *dev __rte_unused,
+ uint32_t mtr_id __rte_unused,
struct rte_mtr_stats *stats __rte_unused,
uint64_t *stats_mask __rte_unused,
int clear __rte_unused,
@@ -888,19 +764,19 @@ bnxt_flow_meter_stats_read(struct rte_eth_dev *dev __rte_unused,
static const struct rte_mtr_ops bnxt_flow_mtr_ops = {
.capabilities_get = bnxt_flow_mtr_cap_get,
- .meter_profile_add = bnxt_flow_meter_profile_add,
- .meter_profile_delete = bnxt_flow_meter_profile_delete,
+ .meter_profile_add = bnxt_flow_mtr_profile_add,
+ .meter_profile_delete = bnxt_flow_mtr_profile_delete,
.meter_policy_validate = NULL,
.meter_policy_add = NULL,
.meter_policy_delete = NULL,
- .create = bnxt_flow_meter_create,
- .destroy = bnxt_flow_meter_destroy,
- .meter_enable = bnxt_flow_meter_enable,
- .meter_disable = bnxt_flow_meter_disable,
- .meter_profile_update = bnxt_flow_meter_profile_update,
+ .create = bnxt_flow_mtr_create,
+ .destroy = bnxt_flow_mtr_destroy,
+ .meter_enable = bnxt_flow_mtr_enable,
+ .meter_disable = bnxt_flow_mtr_disable,
+ .meter_profile_update = bnxt_flow_mtr_profile_update,
.meter_dscp_table_update = NULL,
- .stats_update = bnxt_flow_meter_stats_update,
- .stats_read = bnxt_flow_meter_stats_read,
+ .stats_update = bnxt_flow_mtr_stats_update,
+ .stats_read = bnxt_flow_mtr_stats_read,
};
/**
@@ -910,5 +786,6 @@ int
bnxt_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
{
*(const struct rte_mtr_ops **)arg = &bnxt_flow_mtr_ops;
+
return 0;
}
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp_tf.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp_tf.c
index eb8ecdbace..c7a712b8c8 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp_tf.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp_tf.c
@@ -9,6 +9,8 @@
#include <rte_flow_driver.h>
#include <rte_tailq.h>
#include <rte_spinlock.h>
+#include <rte_mtr.h>
+#include <rte_version.h>
#include "bnxt.h"
#include "bnxt_ulp.h"
@@ -1316,6 +1318,65 @@ ulp_tf_global_cfg_update(struct bnxt *bp,
return rc;
}
+/**
+ * When a port is initialized by dpdk. This functions is called
+ * to enable the meter and initializes the meter global configurations.
+ */
+#define BNXT_THOR_FMTCR_NUM_MET_MET_1K (0x7UL << 20)
+#define BNXT_THOR_FMTCR_CNTRS_ENABLE (0x1UL << 25)
+#define BNXT_THOR_FMTCR_INTERVAL_1K (1024)
+static int32_t
+ulp_tf_flow_mtr_init(struct bnxt *bp)
+{
+ int rc = 0;
+
+ /*
+ * Enable metering. Set the meter global configuration register.
+ * Set number of meter to 1K. Disable the drop counter for now.
+ */
+ rc = ulp_tf_global_cfg_update(bp, TF_DIR_RX, TF_METER_CFG,
+ 0,
+ BNXT_THOR_FMTCR_NUM_MET_MET_1K,
+ 1);
+ if (rc) {
+ BNXT_DRV_DBG(ERR, "Failed to set rx meter configuration\n");
+ goto jump_to_error;
+ }
+
+ rc = ulp_tf_global_cfg_update(bp, TF_DIR_TX, TF_METER_CFG,
+ 0,
+ BNXT_THOR_FMTCR_NUM_MET_MET_1K,
+ 1);
+ if (rc) {
+ BNXT_DRV_DBG(ERR, "Failed to set tx meter configuration\n");
+ goto jump_to_error;
+ }
+
+ /*
+ * Set meter refresh rate to 1024 clock cycle. This value works for
+ * most bit rates especially for high rates.
+ */
+ rc = ulp_tf_global_cfg_update(bp, TF_DIR_RX, TF_METER_INTERVAL_CFG,
+ 0,
+ BNXT_THOR_FMTCR_INTERVAL_1K,
+ 1);
+ if (rc) {
+ BNXT_DRV_DBG(ERR, "Failed to set rx meter interval\n");
+ goto jump_to_error;
+ }
+
+ rc = bnxt_flow_mtr_init(bp);
+ if (rc) {
+ BNXT_DRV_DBG(ERR, "Failed to config meter\n");
+ goto jump_to_error;
+ }
+
+ return rc;
+
+jump_to_error:
+ return rc;
+}
+
/*
* When a port is deinit'ed by dpdk. This function is called
* and this function clears the ULP context and rest of the
@@ -1498,7 +1559,7 @@ ulp_tf_init(struct bnxt *bp,
}
if (ulp_dev_id == BNXT_ULP_DEVICE_ID_THOR) {
- rc = bnxt_flow_meter_init(bp);
+ rc = ulp_tf_flow_mtr_init(bp);
if (rc) {
BNXT_DRV_DBG(ERR, "Failed to config meter\n");
goto jump_to_error;
@@ -1513,11 +1574,59 @@ ulp_tf_init(struct bnxt *bp,
return rc;
}
+/**
+ * Get meter capabilities.
+ */
+#define MAX_FLOW_PER_METER 1024
+#define MAX_METER_RATE_100GBPS ((1ULL << 30) * 100 / 8)
+static int
+ulp_tf_mtr_cap_get(struct bnxt *bp,
+ struct rte_mtr_capabilities *cap)
+{
+ struct tf_get_session_info_parms iparms;
+ struct tf *tfp;
+ int32_t rc = 0;
+
+ /* Get number of meter reserved for this session */
+ memset(&iparms, 0, sizeof(iparms));
+ tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT);
+ rc = tf_get_session_info(tfp, &iparms);
+ if (rc != 0) {
+ BNXT_DRV_DBG(ERR, "Failed to get session resource info\n");
+ return rc;
+ }
+
+ memset(cap, 0, sizeof(struct rte_mtr_capabilities));
+
+ cap->n_max = iparms.session_info.tbl[TF_DIR_RX].info[TF_TBL_TYPE_METER_INST].stride;
+ if (!cap->n_max) {
+ BNXT_DRV_DBG(ERR, "Meter is not supported\n");
+ return -EINVAL;
+ }
+
+#if (RTE_VERSION_NUM(21, 05, 0, 0) <= RTE_VERSION)
+ cap->srtcm_rfc2697_byte_mode_supported = 1;
+#endif
+ cap->n_shared_max = cap->n_max;
+ /* No meter is identical */
+ cap->identical = 1;
+ cap->shared_identical = 1;
+ cap->shared_n_flows_per_mtr_max = MAX_FLOW_PER_METER;
+ cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
+ cap->meter_srtcm_rfc2697_n_max = cap->n_max;
+ cap->meter_rate_max = MAX_METER_RATE_100GBPS;
+ /* No stats supported now */
+ cap->stats_mask = 0;
+
+ return 0;
+}
+
const struct bnxt_ulp_core_ops bnxt_ulp_tf_core_ops = {
.ulp_ctx_attach = ulp_tf_ctx_attach,
.ulp_ctx_detach = ulp_tf_ctx_detach,
.ulp_deinit = ulp_tf_deinit,
.ulp_init = ulp_tf_init,
.ulp_vfr_session_fid_add = NULL,
- .ulp_vfr_session_fid_rem = NULL
+ .ulp_vfr_session_fid_rem = NULL,
+ .ulp_mtr_cap_get = ulp_tf_mtr_cap_get
};
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp_tfc.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp_tfc.c
index e1dd7962d9..a0be2dbb4d 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp_tfc.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp_tfc.c
@@ -9,6 +9,8 @@
#include <rte_flow_driver.h>
#include <rte_tailq.h>
#include <rte_spinlock.h>
+#include <rte_mtr.h>
+#include <rte_version.h>
#include "bnxt.h"
#include "bnxt_ulp.h"
@@ -1018,6 +1020,20 @@ ulp_tfc_init(struct bnxt *bp,
goto jump_to_error;
}
+ rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
+ if (rc) {
+ BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n");
+ return rc;
+ }
+
+ if (ulp_dev_id == BNXT_ULP_DEVICE_ID_THOR2) {
+ rc = bnxt_flow_mtr_init(bp);
+ if (rc) {
+ BNXT_DRV_DBG(ERR, "Failed to config meter\n");
+ goto jump_to_error;
+ }
+ }
+
BNXT_DRV_DBG(DEBUG, "ulp ctx has been initialized\n");
return rc;
@@ -1026,11 +1042,40 @@ ulp_tfc_init(struct bnxt *bp,
return rc;
}
+/**
+ * Get meter capabilities.
+ */
+#define MAX_FLOW_PER_METER 1024
+#define MAX_NUM_METER 1024
+#define MAX_METER_RATE_200GBPS ((1ULL << 31) * 100 / 8)
+static int
+ulp_tfc_mtr_cap_get(struct bnxt *bp __rte_unused,
+ struct rte_mtr_capabilities *cap)
+{
+#if (RTE_VERSION_NUM(21, 05, 0, 0) <= RTE_VERSION)
+ cap->srtcm_rfc2697_byte_mode_supported = 1;
+#endif
+ cap->n_max = MAX_NUM_METER;
+ cap->n_shared_max = cap->n_max;
+ /* No meter is identical */
+ cap->identical = 1;
+ cap->shared_identical = 1;
+ cap->shared_n_flows_per_mtr_max = MAX_FLOW_PER_METER;
+ cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
+ cap->meter_srtcm_rfc2697_n_max = cap->n_max;
+ cap->meter_rate_max = MAX_METER_RATE_200GBPS;
+ /* No stats supported now */
+ cap->stats_mask = 0;
+
+ return 0;
+}
+
const struct bnxt_ulp_core_ops bnxt_ulp_tfc_core_ops = {
.ulp_ctx_attach = ulp_tfc_ctx_attach,
.ulp_ctx_detach = ulp_tfc_ctx_detach,
.ulp_deinit = ulp_tfc_deinit,
.ulp_init = ulp_tfc_init,
.ulp_vfr_session_fid_add = ulp_tfc_vfr_session_fid_add,
- .ulp_vfr_session_fid_rem = ulp_tfc_vfr_session_fid_rem
+ .ulp_vfr_session_fid_rem = ulp_tfc_vfr_session_fid_rem,
+ .ulp_mtr_cap_get = ulp_tfc_mtr_cap_get
};
diff --git a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c
index b647b2b83f..d313b7da07 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c
@@ -3401,13 +3401,11 @@ ulp_rte_meter_act_handler(const struct rte_flow_action *action_item,
}
meter = action_item->conf;
- if (meter) {
- /* validate the mtr_id and update the reference counter */
- tmp_meter_id = tfp_cpu_to_be_32(meter->mtr_id);
- memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER],
- &tmp_meter_id,
- BNXT_ULP_ACT_PROP_SZ_METER);
- }
+ /* validate the mtr_id and update the reference counter */
+ tmp_meter_id = tfp_cpu_to_be_32(meter->mtr_id);
+ memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_METER],
+ &tmp_meter_id,
+ BNXT_ULP_ACT_PROP_SZ_METER);
/* set the meter action header bit */
ULP_BITMAP_SET(params->act_bitmap.bits, BNXT_ULP_ACT_BIT_METER);
--
2.39.3
next prev parent reply other threads:[~2024-10-21 8:19 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-21 8:25 [PATCH v6 00/47] TruFlow update " Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 01/47] net/bnxt: tf_core: fix wc tcam multi slice delete issue Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 02/47] net/bnxt: tf_core: tcam manager data corruption Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 03/47] net/bnxt: tf_core: External EM support cleanup Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 04/47] net/bnxt: tf_core: Thor TF EM key size check Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 05/47] net/bnxt: tf_core: flow scale improvement Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 06/47] net/bnxt: tf_core: TF support flow scale query Sriharsha Basavapatna
2024-10-21 16:09 ` Stephen Hemminger
2024-10-22 16:12 ` Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 07/47] net/bnxt: tf_core: fix slice count in case of HA entry move Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 08/47] net/bnxt: tf_core: convert priority based TCAM manager to dynamic allocation Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 09/47] net/bnxt: tf_core: remove dead AFM code from session-based priority TCAM mgr Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 10/47] net/bnxt: tf_core: remove dead " Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 11/47] net/bnxt: tfc: support tf-core for Thor2 Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 12/47] net/bnxt: tf_ulp: add vxlan-gpe base support Sriharsha Basavapatna
2024-10-21 15:54 ` Stephen Hemminger
2024-10-22 16:07 ` Sriharsha Basavapatna
2024-10-22 21:32 ` Ajit Khaparde
2024-10-23 0:44 ` Stephen Hemminger
2024-10-21 8:25 ` [PATCH v6 13/47] net/bnxt: tf_ulp: add custom l2 etype tunnel support Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 14/47] net/bnxt: tf_ulp: add support for vf to vf flow offload Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 15/47] net/bnxt: tf_ulp: Wh+ mirroring support Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 16/47] net/bnxt: tf_ulp: miscellaneous fixes Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 17/47] net/bnxt: tf_ulp: support for Thor2 ulp layer Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 18/47] net/bnxt: tf_ulp: add support for overlapping flows Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 19/47] net/bnxt: tf_ulp: convert recipe table to dynamic memory Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 20/47] net/bnxt: tf_ulp: add feature bit support Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 21/47] net/bnxt: tf_ulp: add action read and clear support Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 22/47] net/bnxt: tf_ulp: update template files Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 23/47] net/bnxt: tf_ulp: VFR updates for Thor 2 Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 24/47] net/bnxt: tf_ulp: add support for tunnel flow stats Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 25/47] net/bnxt: tf_ulp: update template files Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 26/47] net/bnxt: tf_ulp: enable recipe id generation Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 27/47] net/bnxt: tf_ulp: fixed parent child db counters Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 28/47] net/bnxt: tf_ulp: modify return values to adhere to C coding standard Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 29/47] net/bnxt: tf_ulp: update template files Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 30/47] net/bnxt: tf_ulp: add mask defaults when mask is not specified Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 31/47] net/bnxt: tf_ulp: add jump action support Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 32/47] net/bnxt: tf_ulp: add support for flow priority Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 33/47] net/bnxt: tf_ulp: support for dynamic tunnel ports Sriharsha Basavapatna
2024-10-21 8:25 ` Sriharsha Basavapatna [this message]
2024-10-21 8:25 ` [PATCH v6 35/47] net/bnxt: tf_ulp: TF support flow scale query Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 36/47] net/bnxt: tf_ulp: add support for rss flow query to ULP Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 37/47] net/bnxt: tf_ulp: add track type feature to tables Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 38/47] net/bnxt: tf_ulp: inline utility functions and use likely/unlikely Sriharsha Basavapatna
2024-10-21 8:25 ` [PATCH v6 39/47] net/bnxt: tf_ulp: switch ulp to use rte crc32 hash Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 40/47] net/bnxt: tf_ulp: update template files Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 41/47] net/bnxt: tf_ulp: support a few generic template items Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 42/47] net/bnxt: tf_ulp: TFC support flow scale query for Thor2 Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 43/47] net/bnxt: tf_ulp: update template files Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 44/47] net/bnxt: tf_ulp: enable support for truflow feature configuration Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 45/47] net/bnxt: tf_ulp: support a few feature extensions Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 46/47] net/bnxt: tf_ulp: update template files Sriharsha Basavapatna
2024-10-21 8:26 ` [PATCH v6 47/47] net/bnxt: tf_ulp: add stats cache for thor2 Sriharsha Basavapatna
2024-10-24 5:26 ` [PATCH v6 00/47] TruFlow update for Thor2 Ajit Khaparde
2024-10-28 12:58 ` Thomas Monjalon
2024-10-28 16:32 ` Sriharsha Basavapatna
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=20241021082607.232829-35-sriharsha.basavapatna@broadcom.com \
--to=sriharsha.basavapatna@broadcom.com \
--cc=ajit.khaparde@broadcom.com \
--cc=dev@dpdk.org \
--cc=jay.ding@broadcom.com \
--cc=michael.baucom@broadcom.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).