All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next] nfp: VF rate limit support
@ 2022-04-22 13:19 Simon Horman
  2022-04-25 23:53 ` Jakub Kicinski
  0 siblings, 1 reply; 5+ messages in thread
From: Simon Horman @ 2022-04-22 13:19 UTC (permalink / raw)
  To: David Miller, Jakub Kicinski; +Cc: netdev, oss-drivers, Bin Chen

From: Bin Chen <bin.chen@corigine.com>

This patch enhances the NFP driver to supports assignment of
both max_tx_rate and min_tx_rate to VFs

The following configurations are all supported:
 # ip link set $DEV vf $VF_NUM max_tx_rate $RATE_VALUE
 # ip link set $DEV vf $VF_NUM min_tx_rate $RATE_VALUE
 # ip link set $DEV vf $VF_NUM max_tx_rate $RATE_VALUE \
			       min_tx_rate $RATE_VALUE
 # ip link set $DEV vf $VF_NUM min_tx_rate $RATE_VALUE \
			       max_tx_rate $RATE_VALUE

The max RATE_VALUE is limited to 0xFFFF which is about
63Gbps (using 1024 for 1G).

Signed-off-by: Bin Chen <bin.chen@corigine.com>
Signed-off-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
---
 .../ethernet/netronome/nfp/nfp_net_common.c   |  1 +
 .../ethernet/netronome/nfp/nfp_net_sriov.c    | 50 ++++++++++++++++++-
 .../ethernet/netronome/nfp/nfp_net_sriov.h    |  9 ++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index b412670d89b2..4340b69cc919 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1903,6 +1903,7 @@ const struct net_device_ops nfp_nfd3_netdev_ops = {
 	.ndo_vlan_rx_kill_vid	= nfp_net_vlan_rx_kill_vid,
 	.ndo_set_vf_mac         = nfp_app_set_vf_mac,
 	.ndo_set_vf_vlan        = nfp_app_set_vf_vlan,
+	.ndo_set_vf_rate	= nfp_app_set_vf_rate,
 	.ndo_set_vf_spoofchk    = nfp_app_set_vf_spoofchk,
 	.ndo_set_vf_trust	= nfp_app_set_vf_trust,
 	.ndo_get_vf_config	= nfp_app_get_vf_config,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
index 4627715a5e32..bca0a864cb44 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
@@ -142,6 +142,40 @@ int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
 	return nfp_net_sriov_update(app, vf, update, "vlan");
 }
 
+int nfp_app_set_vf_rate(struct net_device *netdev, int vf,
+			int min_tx_rate, int max_tx_rate)
+{
+	struct nfp_app *app = nfp_app_from_netdev(netdev);
+	u32 vf_offset, ratevalue;
+	int err;
+
+	err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
+	if (err)
+		return err;
+
+	if (max_tx_rate > 0 || min_tx_rate > 0) {
+		if (max_tx_rate > 0 && max_tx_rate < min_tx_rate) {
+			nfp_warn(app->cpp, "min-tx-rate exceeds max_tx_rate.\n");
+			return -EINVAL;
+		}
+
+		if (max_tx_rate > NFP_NET_VF_RATE_MAX || min_tx_rate > NFP_NET_VF_RATE_MAX) {
+			nfp_warn(app->cpp, "tx-rate exceeds 0x%x.\n", NFP_NET_VF_RATE_MAX);
+			return -EINVAL;
+		}
+	}
+
+	vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
+	ratevalue = FIELD_PREP(NFP_NET_VF_CFG_MAX_RATE,
+			       max_tx_rate ? max_tx_rate : NFP_NET_VF_RATE_MAX) |
+		    FIELD_PREP(NFP_NET_VF_CFG_MIN_RATE, min_tx_rate);
+
+	writel(ratevalue, app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE);
+
+	return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_RATE,
+				    "rate");
+}
+
 int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
 {
 	struct nfp_app *app = nfp_app_from_netdev(netdev);
@@ -228,9 +262,8 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
 			  struct ifla_vf_info *ivi)
 {
 	struct nfp_app *app = nfp_app_from_netdev(netdev);
-	unsigned int vf_offset;
+	u32 vf_offset, mac_hi, rate;
 	u32 vlan_tag;
-	u32 mac_hi;
 	u16 mac_lo;
 	u8 flags;
 	int err;
@@ -261,5 +294,18 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
 	ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
 	ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);
 
+	err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
+	if (!err) {
+		rate = readl(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE);
+
+		ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
+		ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate);
+
+		if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
+			ivi->max_tx_rate = 0;
+		if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
+			ivi->max_tx_rate = 0;
+	}
+
 	return 0;
 }
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
index 7b72cc083476..2d445fa199dc 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
@@ -20,6 +20,7 @@
 #define   NFP_NET_VF_CFG_MB_CAP_LINK_STATE		  (0x1 << 3)
 #define   NFP_NET_VF_CFG_MB_CAP_TRUST			  (0x1 << 4)
 #define   NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO		  (0x1 << 5)
+#define   NFP_NET_VF_CFG_MB_CAP_RATE			  (0x1 << 6)
 #define NFP_NET_VF_CFG_MB_RET				0x2
 #define NFP_NET_VF_CFG_MB_UPD				0x4
 #define   NFP_NET_VF_CFG_MB_UPD_MAC			  (0x1 << 0)
@@ -28,6 +29,7 @@
 #define   NFP_NET_VF_CFG_MB_UPD_LINK_STATE		  (0x1 << 3)
 #define   NFP_NET_VF_CFG_MB_UPD_TRUST			  (0x1 << 4)
 #define   NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO		  (0x1 << 5)
+#define   NFP_NET_VF_CFG_MB_UPD_RATE			  (0x1 << 6)
 #define NFP_NET_VF_CFG_MB_VF_NUM			0x7
 
 /* VF config entry
@@ -48,10 +50,17 @@
 #define   NFP_NET_VF_CFG_VLAN_PROT			  0xffff0000
 #define   NFP_NET_VF_CFG_VLAN_QOS			  0xe000
 #define   NFP_NET_VF_CFG_VLAN_VID			  0x0fff
+#define NFP_NET_VF_CFG_RATE				0xc
+#define   NFP_NET_VF_CFG_MIN_RATE			0x0000ffff
+#define   NFP_NET_VF_CFG_MAX_RATE			0xffff0000
+
+#define NFP_NET_VF_RATE_MAX			0xffff
 
 int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac);
 int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
 			__be16 vlan_proto);
+int nfp_app_set_vf_rate(struct net_device *netdev, int vf, int min_tx_rate,
+			int max_tx_rate);
 int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
 int nfp_app_set_vf_trust(struct net_device *netdev, int vf, bool setting);
 int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next] nfp: VF rate limit support
  2022-04-22 13:19 [PATCH net-next] nfp: VF rate limit support Simon Horman
@ 2022-04-25 23:53 ` Jakub Kicinski
  2022-04-29  8:54   ` Bin Chen
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2022-04-25 23:53 UTC (permalink / raw)
  To: Simon Horman; +Cc: David Miller, netdev, oss-drivers, Bin Chen

On Fri, 22 Apr 2022 15:19:45 +0200 Simon Horman wrote:
> +	if (max_tx_rate > 0 || min_tx_rate > 0) {
> +		if (max_tx_rate > 0 && max_tx_rate < min_tx_rate) {
> +			nfp_warn(app->cpp, "min-tx-rate exceeds max_tx_rate.\n");
> +			return -EINVAL;
> +		}

This check should be moved to the core, I reckon.

> +		if (max_tx_rate > NFP_NET_VF_RATE_MAX || min_tx_rate > NFP_NET_VF_RATE_MAX) {

Please wrap the lines at 80 chars, it's actually going to be easier 
to read here.

> +			nfp_warn(app->cpp, "tx-rate exceeds 0x%x.\n", NFP_NET_VF_RATE_MAX);

Does it really make sense to print the rate as hex?

> +			return -EINVAL;
> +		}

> @@ -261,5 +294,18 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
>  	ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
>  	ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);
>  
> +	err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
> +	if (!err) {
> +		rate = readl(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE);
> +
> +		ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
> +		ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate);
> +
> +		if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
> +			ivi->max_tx_rate = 0;

If rate == NFP_NET_VF_RATE_MAX means unset then the check on set should
disallow it, IOW:

	if (max_tx_rate >= NFP_NET_VF_RATE_MAX || 
            min_tx_rate >= NFP_NET_VF_RATE_MAX) {
		nfp_war(...

no?

> +		if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
> +			ivi->max_tx_rate = 0;

*squint* you check min and clear max, is this intentional?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH net-next] nfp: VF rate limit support
  2022-04-25 23:53 ` Jakub Kicinski
@ 2022-04-29  8:54   ` Bin Chen
  2022-04-29 18:03     ` Jakub Kicinski
  0 siblings, 1 reply; 5+ messages in thread
From: Bin Chen @ 2022-04-29  8:54 UTC (permalink / raw)
  To: Jakub Kicinski, Simon Horman; +Cc: David Miller, netdev, oss-drivers

On Tue, 26 Apr 2022 7:53 AM, Jakub wrote:
> On Fri, 22 Apr 2022 15:19:45 +0200 Simon Horman wrote:
> > +	if (max_tx_rate > 0 || min_tx_rate > 0) {
> > +		if (max_tx_rate > 0 && max_tx_rate < min_tx_rate) {
> > +			nfp_warn(app->cpp, "min-tx-rate exceeds max_tx_rate.\n");
> > +			return -EINVAL;
> > +		}
> 
> This check should be moved to the core, I reckon.
>
We agree with your suggestion, thanks. We plan to do this in two steps:
1.The firmware that currently support this feature will reject the nonzero min_tx_rate configuration, so the check here will not step in.  We will remove the check from driver site and upstream the patch. 
2.We will do more investigation jobs and add an appropriate check in the core.
What do you think?

> > +		if (max_tx_rate > NFP_NET_VF_RATE_MAX || min_tx_rate >
> > +NFP_NET_VF_RATE_MAX) {
> 
> Please wrap the lines at 80 chars, it's actually going to be easier to read here.
Accepted. Thank you. 

> 
> > +			nfp_warn(app->cpp, "tx-rate exceeds 0x%x.\n", 
> > +NFP_NET_VF_RATE_MAX);
> 
> Does it really make sense to print the rate as hex?
> 
> > +			return -EINVAL;
> > +		}
> 
Accepted. I will use "%d" instead.


> > @@ -261,5 +294,18 @@ int nfp_app_get_vf_config(struct net_device
> *netdev, int vf,
> >  	ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
> >  	ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);
> >
> > +	err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE,
> "rate");
> > +	if (!err) {
> > +		rate = readl(app->pf->vfcfg_tbl2 + vf_offset + 
> > +NFP_NET_VF_CFG_RATE);
> > +
> > +		ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
> > +		ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate);
> > +
> > +		if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
> > +			ivi->max_tx_rate = 0;
> 
> If rate == NFP_NET_VF_RATE_MAX means unset then the check on set 
> should disallow it, IOW:
> 
> 	if (max_tx_rate >= NFP_NET_VF_RATE_MAX ||
>             min_tx_rate >= NFP_NET_VF_RATE_MAX) {
> 		nfp_war(...
> 
> no?
>
Yes, there is a bug,thank you for catching it. I will enhance the check on set as your suggestion.


> > +		if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
> > +			ivi->max_tx_rate = 0;
> 
> *squint* you check min and clear max, is this intentional?
It is not intentional to do, it must be an accident. I will fix it. Thank you.

> -----Original Message-----
> From: Jakub Kicinski <kuba@kernel.org>
> Sent: 2022.4.6 7:53
> To: Simon Horman <simon.horman@corigine.com>
> Cc: David Miller <davem@davemloft.net>; netdev@vger.kernel.org; oss-
> drivers <oss-drivers@corigine.com>; Bin Chen <bin.chen@corigine.com>
> Subject: Re: [PATCH net-next] nfp: VF rate limit support
> 
> On Fri, 22 Apr 2022 15:19:45 +0200 Simon Horman wrote:
> > +	if (max_tx_rate > 0 || min_tx_rate > 0) {
> > +		if (max_tx_rate > 0 && max_tx_rate < min_tx_rate) {
> > +			nfp_warn(app->cpp, "min-tx-rate exceeds
> max_tx_rate.\n");
> > +			return -EINVAL;
> > +		}
> 
> This check should be moved to the core, I reckon.
> 
> > +		if (max_tx_rate > NFP_NET_VF_RATE_MAX || min_tx_rate >
> > +NFP_NET_VF_RATE_MAX) {
> 
> Please wrap the lines at 80 chars, it's actually going to be easier to read here.
> 
> > +			nfp_warn(app->cpp, "tx-rate exceeds 0x%x.\n",
> > +NFP_NET_VF_RATE_MAX);
> 
> Does it really make sense to print the rate as hex?
> 
> > +			return -EINVAL;
> > +		}
> 
> > @@ -261,5 +294,18 @@ int nfp_app_get_vf_config(struct net_device
> *netdev, int vf,
> >  	ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
> >  	ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE,
> flags);
> >
> > +	err = nfp_net_sriov_check(app, vf,
> NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
> > +	if (!err) {
> > +		rate = readl(app->pf->vfcfg_tbl2 + vf_offset +
> > +NFP_NET_VF_CFG_RATE);
> > +
> > +		ivi->max_tx_rate =
> FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
> > +		ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE,
> rate);
> > +
> > +		if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
> > +			ivi->max_tx_rate = 0;
> 
> If rate == NFP_NET_VF_RATE_MAX means unset then the check on set
> should disallow it, IOW:
> 
> 	if (max_tx_rate >= NFP_NET_VF_RATE_MAX ||
>             min_tx_rate >= NFP_NET_VF_RATE_MAX) {
> 		nfp_war(...
> 
> no?
> 
> > +		if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
> > +			ivi->max_tx_rate = 0;
> 
> *squint* you check min and clear max, is this intentional?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next] nfp: VF rate limit support
  2022-04-29  8:54   ` Bin Chen
@ 2022-04-29 18:03     ` Jakub Kicinski
  2022-04-29 18:04       ` Jakub Kicinski
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2022-04-29 18:03 UTC (permalink / raw)
  To: Bin Chen; +Cc: Simon Horman, David Miller, netdev, oss-drivers

On Fri, 29 Apr 2022 08:54:53 +0000 Bin Chen wrote:
> On Tue, 26 Apr 2022 7:53 AM, Jakub wrote:
> > On Fri, 22 Apr 2022 15:19:45 +0200 Simon Horman wrote:  
> > > +	if (max_tx_rate > 0 || min_tx_rate > 0) {
> > > +		if (max_tx_rate > 0 && max_tx_rate < min_tx_rate) {
> > > +			nfp_warn(app->cpp, "min-tx-rate exceeds max_tx_rate.\n");
> > > +			return -EINVAL;
> > > +		}  
> > 
> > This check should be moved to the core, I reckon.
> >  
> We agree with your suggestion, thanks. We plan to do this in two steps:
> 1.The firmware that currently support this feature will reject the nonzero min_tx_rate configuration, so the check here will not step in.  We will remove the check from driver site and upstream the patch. 
> 2.We will do more investigation jobs and add an appropriate check in the core.
> What do you think?

Sorry, I meant the second part of the condition only, basically
something like:


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next] nfp: VF rate limit support
  2022-04-29 18:03     ` Jakub Kicinski
@ 2022-04-29 18:04       ` Jakub Kicinski
  0 siblings, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2022-04-29 18:04 UTC (permalink / raw)
  To: Bin Chen; +Cc: Simon Horman, David Miller, netdev, oss-drivers

On Fri, 29 Apr 2022 11:03:47 -0700 Jakub Kicinski wrote:
> On Fri, 29 Apr 2022 08:54:53 +0000 Bin Chen wrote:
> > We agree with your suggestion, thanks. We plan to do this in two steps:
> > 1.The firmware that currently support this feature will reject the nonzero min_tx_rate configuration, so the check here will not step in.  We will remove the check from driver site and upstream the patch. 
> > 2.We will do more investigation jobs and add an appropriate check in the core.
> > What do you think?  
> 
> Sorry, I meant the second part of the condition only, basically
> something like:

I hit the wrong shortcut :) Here's the patch:

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 73f2cbc440c9..8de191cedaf7 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2368,6 +2368,19 @@ static int handle_vf_guid(struct net_device *dev, struct ifla_vf_guid *ivt, int
 	return handle_infiniband_guid(dev, ivt, guid_type);
 }
 
+static int rtnl_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
+			    int max_tx_rate)
+{
+	int err;
+
+	if (!ops->ndo_set_vf_rate)
+		return -EOPNOTSUPP;
+	if (min_tx_rate > max_tx_rate)
+		return -EINVAL;
+
+	return ops->ndo_set_vf_rate(dev, vf, min_tx_rate, max_tx_rate);
+}
+
 static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
@@ -2443,11 +2456,8 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
 		if (err < 0)
 			return err;
 
-		err = -EOPNOTSUPP;
-		if (ops->ndo_set_vf_rate)
-			err = ops->ndo_set_vf_rate(dev, ivt->vf,
-						   ivf.min_tx_rate,
-						   ivt->rate);
+		err = rtnl_set_vf_rate(dev, ivt->vf,
+				       ivf.min_tx_rate, ivt->rate);
 		if (err < 0)
 			return err;
 	}
@@ -2457,11 +2467,8 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
 
 		if (ivt->vf >= INT_MAX)
 			return -EINVAL;
-		err = -EOPNOTSUPP;
-		if (ops->ndo_set_vf_rate)
-			err = ops->ndo_set_vf_rate(dev, ivt->vf,
-						   ivt->min_tx_rate,
-						   ivt->max_tx_rate);
+		err = rtnl_set_vf_rate(dev, ivt->vf,
+				       ivt->min_tx_rate, ivt->max_tx_rate);
 		if (err < 0)
 			return err;
 	}

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-04-29 18:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-22 13:19 [PATCH net-next] nfp: VF rate limit support Simon Horman
2022-04-25 23:53 ` Jakub Kicinski
2022-04-29  8:54   ` Bin Chen
2022-04-29 18:03     ` Jakub Kicinski
2022-04-29 18:04       ` Jakub Kicinski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.