All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vipin Varghese <vipin.varghese@intel.com>
To: dev@dpdk.org, thomas@monjalon.net, john.mcnamara@intel.com
Cc: konstantin.ananyev@intel.com, stephen@networkplumber.org,
	reshma.pattan@intel.com, jasvinder.singh@intel.com,
	stephen1.byrne@intel.com, amol.patel@intel.com,
	Vipin Varghese <vipin.varghese@intel.com>
Subject: [PATCH v9 2/6] app/procinfo: add support for show tm
Date: Fri, 11 Jan 2019 03:06:41 +0530	[thread overview]
Message-ID: <20190110213645.29901-3-vipin.varghese@intel.com> (raw)
In-Reply-To: <20190110213645.29901-1-vipin.varghese@intel.com>

Function show_tm is used for displaying the tm PMD under the primary
process. This covers basic and per node|level details with statistics.

Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
Acked-by: Reshma  Pattan <reshma.pattan@intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---
 app/proc-info/main.c           | 290 ++++++++++++++++++++++++++++++++-
 doc/guides/tools/proc_info.rst |   6 +-
 2 files changed, 294 insertions(+), 2 deletions(-)

diff --git a/app/proc-info/main.c b/app/proc-info/main.c
index 2108c24b0..ea15ae1a6 100644
--- a/app/proc-info/main.c
+++ b/app/proc-info/main.c
@@ -32,6 +32,7 @@
 #include <rte_cycles.h>
 #include <rte_security.h>
 #include <rte_cryptodev.h>
+#include <rte_tm.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -77,6 +78,8 @@ static char bdr_str[MAX_STRING_LEN];
 
 /**< Enable show port. */
 static uint32_t enable_shw_port;
+/**< Enable show tm. */
+static uint32_t enable_shw_tm;
 
 /**< display usage */
 static void
@@ -97,7 +100,8 @@ proc_info_usage(const char *prgname)
 		"  --xstats-reset: to reset port extended statistics\n"
 		"  --collectd-format: to print statistics to STDOUT in expected by collectd format\n"
 		"  --host-id STRING: host id used to identify the system process is running on\n"
-		"  --show-port: to display ports information\n",
+		"  --show-port: to display ports information\n"
+		"  --show-tm: to display traffic manager information for ports\n",
 		prgname);
 }
 
@@ -205,6 +209,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"xstats-ids", 1, NULL, 1},
 		{"host-id", 0, NULL, 0},
 		{"show-port", 0, NULL, 0},
+		{"show-tm", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
 
@@ -251,6 +256,9 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name,
 					"show-port", MAX_LONG_OPT_SZ))
 				enable_shw_port = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"show-tm", MAX_LONG_OPT_SZ))
+				enable_shw_tm = 1;
 			break;
 		case 1:
 			/* Print xstat single value given by name*/
@@ -694,6 +702,284 @@ show_port(void)
 	STATS_BDR_STR(50, "");
 }
 
+static void
+display_nodecap_info(int is_leaf, struct rte_tm_node_capabilities *cap)
+{
+	if (cap == NULL)
+		return;
+
+	if (!is_leaf) {
+		printf("\t  -- nonleaf sched max:\n"
+			"\t\t  + children (%u)\n"
+			"\t\t  + sp priorities (%u)\n"
+			"\t\t  + wfq children per group (%u)\n"
+			"\t\t  + wfq groups (%u)\n"
+			"\t\t  + wfq weight (%u)\n",
+			cap->nonleaf.sched_n_children_max,
+			cap->nonleaf.sched_sp_n_priorities_max,
+			cap->nonleaf.sched_wfq_n_children_per_group_max,
+			cap->nonleaf.sched_wfq_n_groups_max,
+			cap->nonleaf.sched_wfq_weight_max);
+	} else {
+		printf("\t  -- leaf cman support:\n"
+			"\t\t  + wred pkt mode (%d)\n"
+			"\t\t  + wred byte mode (%d)\n"
+			"\t\t  + head drop (%d)\n"
+			"\t\t  + wred context private (%d)\n"
+			"\t\t  + wred context shared (%u)\n",
+			cap->leaf.cman_wred_packet_mode_supported,
+			cap->leaf.cman_wred_byte_mode_supported,
+			cap->leaf.cman_head_drop_supported,
+			cap->leaf.cman_wred_context_private_supported,
+			cap->leaf.cman_wred_context_shared_n_max);
+	}
+}
+
+static void
+display_levelcap_info(int is_leaf, struct rte_tm_level_capabilities *cap)
+{
+	if (cap == NULL)
+		return;
+
+	if (!is_leaf) {
+		printf("\t  -- shaper private: (%d) dual rate (%d)\n",
+			cap->nonleaf.shaper_private_supported,
+			cap->nonleaf.shaper_private_dual_rate_supported);
+		printf("\t  -- shaper share: (%u)\n",
+			cap->nonleaf.shaper_shared_n_max);
+		printf("\t  -- non leaf sched MAX:\n"
+			"\t\t  + children (%u)\n"
+			"\t\t  + sp (%u)\n"
+			"\t\t  + wfq children per group (%u)\n"
+			"\t\t  + wfq groups (%u)\n"
+			"\t\t  + wfq weight (%u)\n",
+			cap->nonleaf.sched_n_children_max,
+			cap->nonleaf.sched_sp_n_priorities_max,
+			cap->nonleaf.sched_wfq_n_children_per_group_max,
+			cap->nonleaf.sched_wfq_n_groups_max,
+			cap->nonleaf.sched_wfq_weight_max);
+	} else {
+		printf("\t  -- shaper private: (%d) dual rate (%d)\n",
+			cap->leaf.shaper_private_supported,
+			cap->leaf.shaper_private_dual_rate_supported);
+		printf("\t  -- shaper share: (%u)\n",
+			cap->leaf.shaper_shared_n_max);
+		printf("  -- leaf cman support:\n"
+			"\t\t  + wred pkt mode (%d)\n"
+			"\t\t  + wred byte mode (%d)\n"
+			"\t\t  + head drop (%d)\n"
+			"\t\t  + wred context private (%d)\n"
+			"\t\t  + wred context shared (%u)\n",
+			cap->leaf.cman_wred_packet_mode_supported,
+			cap->leaf.cman_wred_byte_mode_supported,
+			cap->leaf.cman_head_drop_supported,
+			cap->leaf.cman_wred_context_private_supported,
+			cap->leaf.cman_wred_context_shared_n_max);
+	}
+}
+
+static void
+show_tm(void)
+{
+	int ret = 0, check_for_leaf = 0, is_leaf = 0;
+	unsigned int j, k;
+	uint16_t i = 0;
+
+	snprintf(bdr_str, MAX_STRING_LEN, " show - TM PMD %"PRIu64,
+			rte_get_tsc_hz());
+	STATS_BDR_STR(10, bdr_str);
+
+	RTE_ETH_FOREACH_DEV(i) {
+		struct rte_eth_dev_info dev_info;
+		struct rte_tm_capabilities cap;
+		struct rte_tm_error error;
+		struct rte_tm_node_capabilities capnode;
+		struct rte_tm_level_capabilities caplevel;
+		uint32_t n_leaf_nodes = 0;
+
+		memset(&cap, 0, sizeof(cap));
+		memset(&error, 0, sizeof(error));
+
+		rte_eth_dev_info_get(i, &dev_info);
+		printf("  - Generic for port (%u)\n"
+			"\t  -- driver name %s\n"
+			"\t  -- max vf (%u)\n"
+			"\t  -- max tx queues (%u)\n"
+			"\t  -- number of tx queues (%u)\n",
+			i,
+			dev_info.driver_name,
+			dev_info.max_vfs,
+			dev_info.max_tx_queues,
+			dev_info.nb_tx_queues);
+
+		ret = rte_tm_capabilities_get(i, &cap, &error);
+		if (ret)
+			continue;
+
+		printf("  - MAX: nodes (%u) levels (%u) children (%u)\n",
+			cap.n_nodes_max,
+			cap.n_levels_max,
+			cap.sched_n_children_max);
+
+		printf("  - identical nodes: non leaf (%d) leaf (%d)\n",
+			cap.non_leaf_nodes_identical,
+			cap.leaf_nodes_identical);
+
+		printf("  - Shaper MAX:\n"
+			"\t  -- total (%u)\n"
+			"\t  -- private (%u) private dual (%d)\n"
+			"\t  -- shared (%u) shared dual (%u)\n",
+			cap.shaper_n_max,
+			cap.shaper_private_n_max,
+			cap.shaper_private_dual_rate_n_max,
+			cap.shaper_shared_n_max,
+			cap.shaper_shared_dual_rate_n_max);
+
+		printf("  - mark support:\n");
+		printf("\t  -- vlan dei: GREEN (%d) YELLOW (%d) RED (%d)\n",
+			cap.mark_vlan_dei_supported[RTE_TM_GREEN],
+			cap.mark_vlan_dei_supported[RTE_TM_YELLOW],
+			cap.mark_vlan_dei_supported[RTE_TM_RED]);
+		printf("\t  -- ip ecn tcp: GREEN (%d) YELLOW (%d) RED (%d)\n",
+			cap.mark_ip_ecn_tcp_supported[RTE_TM_GREEN],
+			cap.mark_ip_ecn_tcp_supported[RTE_TM_YELLOW],
+			cap.mark_ip_ecn_tcp_supported[RTE_TM_RED]);
+		printf("\t  -- ip ecn sctp: GREEN (%d) YELLOW (%d) RED (%d)\n",
+			cap.mark_ip_ecn_sctp_supported[RTE_TM_GREEN],
+			cap.mark_ip_ecn_sctp_supported[RTE_TM_YELLOW],
+			cap.mark_ip_ecn_sctp_supported[RTE_TM_RED]);
+		printf("\t  -- ip dscp: GREEN (%d) YELLOW (%d) RED (%d)\n",
+			cap.mark_ip_dscp_supported[RTE_TM_GREEN],
+			cap.mark_ip_dscp_supported[RTE_TM_YELLOW],
+			cap.mark_ip_dscp_supported[RTE_TM_RED]);
+
+		printf("  - mask stats (0x%"PRIx64")"
+			" dynamic update (0x%"PRIx64")\n",
+			cap.stats_mask,
+			cap.dynamic_update_mask);
+
+		printf("  - sched MAX:\n"
+			"\t  -- total (%u)\n"
+			"\t  -- sp levels (%u)\n"
+			"\t  -- wfq children per group (%u)\n"
+			"\t  -- wfq groups (%u)\n"
+			"\t  -- wfq weight (%u)\n",
+			cap.sched_sp_n_priorities_max,
+			cap.sched_sp_n_priorities_max,
+			cap.sched_wfq_n_children_per_group_max,
+			cap.sched_wfq_n_groups_max,
+			cap.sched_wfq_weight_max);
+
+		printf("  - CMAN support:\n"
+			"\t  -- WRED mode: pkt (%d) byte (%d)\n"
+			"\t  -- head drop (%d)\n",
+			cap.cman_wred_packet_mode_supported,
+			cap.cman_wred_byte_mode_supported,
+			cap.cman_head_drop_supported);
+		printf("\t  -- MAX WRED CONTEXT:"
+			" total (%u) private (%u) shared (%u)\n",
+			cap.cman_wred_context_n_max,
+			cap.cman_wred_context_private_n_max,
+			cap.cman_wred_context_shared_n_max);
+
+		for (j = 0; j < cap.n_nodes_max; j++) {
+			memset(&capnode, 0, sizeof(capnode));
+			ret = rte_tm_node_capabilities_get(i, j,
+					&capnode, &error);
+			if (ret)
+				continue;
+
+			check_for_leaf = 1;
+
+			printf("  NODE %u\n", j);
+			printf("\t  - shaper private: (%d) dual rate (%d)\n",
+				capnode.shaper_private_supported,
+				capnode.shaper_private_dual_rate_supported);
+			printf("\t  - shaper shared max: (%u)\n",
+				capnode.shaper_shared_n_max);
+			printf("\t  - stats mask %"PRIx64"\n",
+				capnode.stats_mask);
+
+			ret = rte_tm_node_type_get(i, j, &is_leaf, &error);
+			if (ret)
+				continue;
+
+			display_nodecap_info(is_leaf, &capnode);
+		}
+
+		for (j = 0; j < cap.n_levels_max; j++) {
+			memset(&caplevel, 0, sizeof(caplevel));
+			ret = rte_tm_level_capabilities_get(i, j,
+					&caplevel, &error);
+			if (ret)
+				continue;
+
+			printf("  - Level %u\n", j);
+			printf("\t  -- node MAX: %u non leaf %u leaf %u\n",
+				caplevel.n_nodes_max,
+				caplevel.n_nodes_nonleaf_max,
+				caplevel.n_nodes_leaf_max);
+			printf("\t  -- indetical: non leaf %u leaf %u\n",
+				caplevel.non_leaf_nodes_identical,
+				caplevel.leaf_nodes_identical);
+
+			for (k = 0; k < caplevel.n_nodes_max; k++) {
+				ret = rte_tm_node_type_get(i, k,
+					&is_leaf, &error);
+				if (ret)
+					continue;
+
+				display_levelcap_info(is_leaf, &caplevel);
+			}
+		}
+
+		if (check_for_leaf) {
+			ret = rte_tm_get_number_of_leaf_nodes(i,
+					&n_leaf_nodes, &error);
+			if (ret == 0)
+				printf("  - leaf nodes (%u)\n", n_leaf_nodes);
+		}
+
+		for (j = 0; j < n_leaf_nodes; j++) {
+			struct rte_tm_node_stats stats;
+			memset(&stats, 0, sizeof(stats));
+
+			ret = rte_tm_node_stats_read(i, j,
+					&stats, &cap.stats_mask, 0, &error);
+			if (ret)
+				continue;
+
+			printf("  - STATS for node (%u)\n", j);
+			printf("  -- pkts (%"PRIu64") bytes (%"PRIu64")\n",
+				stats.n_pkts, stats.n_bytes);
+
+			ret = rte_tm_node_type_get(i, j, &is_leaf, &error);
+			if (ret || (!is_leaf))
+				continue;
+
+			printf("  -- leaf queued:"
+				" pkts (%"PRIu64") bytes (%"PRIu64")\n",
+				stats.leaf.n_pkts_queued,
+				stats.leaf.n_bytes_queued);
+			printf("  - dropped:\n"
+				"\t  -- GREEN:"
+				" pkts (%"PRIu64") bytes (%"PRIu64")\n"
+				"\t  -- YELLOW:"
+				" pkts (%"PRIu64") bytes (%"PRIu64")\n"
+				"\t  -- RED:"
+				" pkts (%"PRIu64") bytes (%"PRIu64")\n",
+				stats.leaf.n_pkts_dropped[RTE_TM_GREEN],
+				stats.leaf.n_bytes_dropped[RTE_TM_GREEN],
+				stats.leaf.n_pkts_dropped[RTE_TM_YELLOW],
+				stats.leaf.n_bytes_dropped[RTE_TM_YELLOW],
+				stats.leaf.n_pkts_dropped[RTE_TM_RED],
+				stats.leaf.n_bytes_dropped[RTE_TM_RED]);
+		}
+	}
+
+	STATS_BDR_STR(50, "");
+}
+
 int
 main(int argc, char **argv)
 {
@@ -777,6 +1063,8 @@ main(int argc, char **argv)
 	/* show information for PMD */
 	if (enable_shw_port)
 		show_port();
+	if (enable_shw_tm)
+		show_tm();
 
 	ret = rte_eal_cleanup();
 	if (ret)
diff --git a/doc/guides/tools/proc_info.rst b/doc/guides/tools/proc_info.rst
index 6baa1db9a..5f9afdb79 100644
--- a/doc/guides/tools/proc_info.rst
+++ b/doc/guides/tools/proc_info.rst
@@ -18,7 +18,7 @@ The application has a number of command line options:
 .. code-block:: console
 
    ./$(RTE_TARGET)/app/dpdk-procinfo -- -m | [-p PORTMASK] [--stats | --xstats |
-   --stats-reset | --xstats-reset] [ --show-port ]
+   --stats-reset | --xstats-reset] [ --show-port | --show-tm ]
 
 Parameters
 ~~~~~~~~~~
@@ -46,6 +46,10 @@ If no port mask is specified xstats are reset for all DPDK ports.
 The show-port parameter displays port level various configuration informationi
 associated to RX port queue pair.
 
+**--show-tm**
+The show-tm parameter displays per port traffic manager settings, current
+configurations and statistics.
+
 Limitations
 -----------
 
-- 
2.17.1

  parent reply	other threads:[~2019-01-10 15:40 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-22 14:15 [PATCH v5 1/9] app/procinfo: add usage for new debug Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 2/9] app/procinfo: add compare for new options Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 3/9] app/procinfo: add prototype for debug instances Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 4/9] app/procinfo: add support for show port Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 5/9] app/procinfo: add support for show tm Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 6/9] app/procinfo: add support for show crypto Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 7/9] app/procinfo: add support for debug ring Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 8/9] app/procinfo: add support for show mempool Vipin Varghese
2018-11-22 14:15 ` [PATCH v5 9/9] doc/procinfo: add information for debug options Vipin Varghese
2018-11-22 18:08   ` Mcnamara, John
2018-11-23  4:58     ` Varghese, Vipin
2018-12-03  5:49 ` [PATCH v6 0/9] app/proc-info: improve debug of proc-info tool Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 1/9] app/procinfo: add usage for new debug Vipin Varghese
2018-12-12 14:14     ` Pattan, Reshma
2018-12-12 15:06       ` Varghese, Vipin
2018-12-13  5:08     ` [PATCH v7 0/9] app/proc-info: improve debug of proc-info tool Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 1/9] app/procinfo: add usage for new debug Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 2/9] app/procinfo: add compare for new options Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 3/9] app/procinfo: add prototype for debug instances Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 4/9] app/procinfo: add support for show port Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 5/9] app/procinfo: add support for show tm Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 6/9] app/procinfo: add support for show crypto Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 7/9] app/procinfo: add support for debug ring Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 8/9] app/procinfo: add support for show iter mempool Vipin Varghese
2018-12-13  5:08       ` [PATCH v7 9/9] doc/procinfo: add information for debug options Vipin Varghese
2018-12-13 14:42       ` [PATCH v7 0/9] app/proc-info: improve debug of proc-info tool Pattan, Reshma
2018-12-13 16:21         ` Varghese, Vipin
2018-12-22 21:02           ` Thomas Monjalon
2018-12-26  5:21             ` Varghese, Vipin
2018-12-26 21:33               ` Thomas Monjalon
2018-12-27  2:46                 ` Varghese, Vipin
2018-12-27  9:32                   ` Thomas Monjalon
2018-12-27 10:45                     ` Varghese, Vipin
2019-01-07 15:38       ` [PATCH v8 0/7] app/proc-info: enhance " Vipin Varghese
2019-01-07 15:38         ` [PATCH v8 1/7] app/procinfo: prepare for new debug functions Vipin Varghese
2019-01-09 23:45           ` Thomas Monjalon
2019-01-10  3:08             ` Varghese, Vipin
2019-01-10  8:39               ` Thomas Monjalon
2019-01-10  8:53                 ` Varghese, Vipin
2019-01-10  9:09                   ` Thomas Monjalon
2019-01-10 21:36           ` [PATCH v9 0/6] app/proc-info: enhance debug of proc-info tool Vipin Varghese
2019-01-10 21:36             ` [PATCH v9 1/6] app/procinfo: add support for show port Vipin Varghese
2019-01-10 17:40               ` Thomas Monjalon
2019-01-11  3:57                 ` Varghese, Vipin
2019-01-11 10:22                   ` Thomas Monjalon
2019-01-10 21:36             ` Vipin Varghese [this message]
2019-01-10 21:36             ` [PATCH v9 3/6] app/procinfo: add support for show crypto Vipin Varghese
2019-01-10 21:36             ` [PATCH v9 4/6] app/procinfo: add support for debug ring Vipin Varghese
2019-01-10 21:36             ` [PATCH v9 5/6] app/procinfo: add support for show mempool Vipin Varghese
2019-01-10 21:36             ` [PATCH v9 6/6] app/procinfo: add support for iter mempool Vipin Varghese
2019-01-11 14:46             ` [PATCH v9 0/6] app/proc-info: enhance debug of proc-info tool Thomas Monjalon
2019-01-14  0:07               ` Varghese, Vipin
2019-01-07 15:38         ` [PATCH v8 2/7] app/procinfo: add support for show port Vipin Varghese
2019-01-07 15:38         ` [PATCH v8 3/7] app/procinfo: add support for show tm Vipin Varghese
2019-01-07 15:38         ` [PATCH v8 4/7] app/procinfo: add support for show crypto Vipin Varghese
2019-01-07 15:38         ` [PATCH v8 5/7] app/procinfo: add support for debug ring Vipin Varghese
2019-01-07 15:38         ` [PATCH v8 6/7] app/procinfo: add support for show mempool Vipin Varghese
2019-01-07 15:38         ` [PATCH v8 7/7] app/procinfo: add support for iter mempool Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 2/9] app/procinfo: add compare for new options Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 3/9] app/procinfo: add prototype for debug instances Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 4/9] app/procinfo: add support for show port Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 5/9] app/procinfo: add support for show tm Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 6/9] app/procinfo: add support for show crypto Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 7/9] app/procinfo: add support for debug ring Vipin Varghese
2018-12-03  5:49   ` [PATCH v6 8/9] app/procinfo: add support for show iter mempool Vipin Varghese
2018-12-12 16:10     ` Pattan, Reshma
2018-12-13  2:26       ` Varghese, Vipin
2018-12-03  5:50   ` [PATCH v6 9/9] doc/procinfo: add information for debug options Vipin Varghese

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=20190110213645.29901-3-vipin.varghese@intel.com \
    --to=vipin.varghese@intel.com \
    --cc=amol.patel@intel.com \
    --cc=dev@dpdk.org \
    --cc=jasvinder.singh@intel.com \
    --cc=john.mcnamara@intel.com \
    --cc=konstantin.ananyev@intel.com \
    --cc=reshma.pattan@intel.com \
    --cc=stephen1.byrne@intel.com \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    /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 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.