From: Nithin Dabilpuram <ndabilpuram@marvell.com>
To: Wenzhuo Lu <wenzhuo.lu@intel.com>,
Jingjing Wu <jingjing.wu@intel.com>,
Bernard Iremonger <bernard.iremonger@intel.com>,
John McNamara <john.mcnamara@intel.com>,
Marko Kovacevic <marko.kovacevic@intel.com>
Cc: <dev@dpdk.org>, <jerinj@marvell.com>, <kkanas@marvell.com>,
"Nithin Dabilpuram" <ndabilpuram@marvell.com>
Subject: [dpdk-dev] [PATCH 2/2] app/testpmd: add tm non leaf node pktmode command
Date: Mon, 30 Mar 2020 21:30:19 +0530 [thread overview]
Message-ID: <20200330160019.29674-2-ndabilpuram@marvell.com> (raw)
In-Reply-To: <20200330160019.29674-1-ndabilpuram@marvell.com>
Add TM command to enable packet mode for all SP children
in non leaf node. This is a new command as
"add tm nonleaf node pktmode".
This patch also dumps new tm capabilities
"sched_wfq_weight_mode_supported" and "sched_shaper_private_weight_mode".
Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---
app/test-pmd/cmdline.c | 7 ++
app/test-pmd/cmdline_tm.c | 178 ++++++++++++++++++++++++++++
app/test-pmd/cmdline_tm.h | 1 +
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 27 +++++
4 files changed, 213 insertions(+)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index a037a55..eba79f1 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1221,6 +1221,12 @@ static void cmd_help_long_parsed(void *parsed_result,
" [(shared_shaper_id_0) (shared_shaper_id_1)...]\n"
" Add port tm nonleaf node.\n\n"
+ "add port tm nonleaf node pktmode (port_id) (node_id) (parent_node_id)"
+ " (priority) (weight) (level_id) (shaper_profile_id)"
+ " (n_sp_priorities) (stats_mask) (n_shared_shapers)"
+ " [(shared_shaper_id_0) (shared_shaper_id_1)...]\n"
+ " Add port tm nonleaf node with pkt mode enabled.\n\n"
+
"add port tm leaf node (port_id) (node_id) (parent_node_id)"
" (priority) (weight) (level_id) (shaper_profile_id)"
" (cman_mode) (wred_profile_id) (stats_mask) (n_shared_shapers)"
@@ -19583,6 +19589,7 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_del_port_tm_node_wred_profile,
(cmdline_parse_inst_t *)&cmd_set_port_tm_node_shaper_profile,
(cmdline_parse_inst_t *)&cmd_add_port_tm_nonleaf_node,
+ (cmdline_parse_inst_t *)&cmd_add_port_tm_nonleaf_node_pmode,
(cmdline_parse_inst_t *)&cmd_add_port_tm_leaf_node,
(cmdline_parse_inst_t *)&cmd_del_port_tm_node,
(cmdline_parse_inst_t *)&cmd_set_port_tm_node_parent,
diff --git a/app/test-pmd/cmdline_tm.c b/app/test-pmd/cmdline_tm.c
index d62a4f5..269a4b1 100644
--- a/app/test-pmd/cmdline_tm.c
+++ b/app/test-pmd/cmdline_tm.c
@@ -283,6 +283,10 @@ static void cmd_show_port_tm_cap_parsed(void *parsed_result,
cap.sched_wfq_n_groups_max);
printf("cap.sched_wfq_weight_max %" PRIu32 "\n",
cap.sched_wfq_weight_max);
+ printf("cap.sched_wfq_weight_mode_supported %" PRId32 "\n",
+ cap.sched_wfq_weight_mode_supported);
+ printf("cap.sched_shaper_private_weight_mode %" PRId32 "\n",
+ cap.sched_shaper_private_weight_mode);
printf("cap.cman_head_drop_supported %" PRId32 "\n",
cap.cman_head_drop_supported);
printf("cap.cman_wred_context_n_max %" PRIu32 "\n",
@@ -413,6 +417,10 @@ static void cmd_show_port_tm_level_cap_parsed(void *parsed_result,
lcap.nonleaf.sched_wfq_n_groups_max);
printf("cap.nonleaf.sched_wfq_weight_max %" PRIu32 "\n",
lcap.nonleaf.sched_wfq_weight_max);
+ printf("cap.nonleaf.sched_wfq_weight_mode_supported %" PRId32 "\n",
+ lcap.nonleaf.sched_wfq_weight_mode_supported);
+ printf("cap.nonleaf.sched_shaper_private_weight_mode %" PRId32 "\n",
+ lcap.nonleaf.sched_shaper_private_weight_mode);
printf("cap.nonleaf.stats_mask %" PRIx64 "\n",
lcap.nonleaf.stats_mask);
} else {
@@ -537,6 +545,10 @@ static void cmd_show_port_tm_node_cap_parsed(void *parsed_result,
ncap.nonleaf.sched_wfq_n_groups_max);
printf("cap.nonleaf.sched_wfq_weight_max %" PRIu32 "\n",
ncap.nonleaf.sched_wfq_weight_max);
+ printf("cap.nonleaf.sched_wfq_weight_mode_supported %" PRId32 "\n",
+ ncap.nonleaf.sched_wfq_weight_mode_supported);
+ printf("cap.nonleaf.sched_shaper_private_weight_mode %" PRId32 "\n",
+ ncap.nonleaf.sched_shaper_private_weight_mode);
} else {
printf("cap.leaf.cman_head_drop_supported %" PRId32 "\n",
ncap.leaf.cman_head_drop_supported);
@@ -1671,6 +1683,172 @@ cmdline_parse_inst_t cmd_add_port_tm_nonleaf_node = {
},
};
+/* *** Add Port TM nonleaf node pkt mode *** */
+struct cmd_add_port_tm_nonleaf_node_pmode_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t nonleaf;
+ cmdline_fixed_string_t node;
+ uint16_t port_id;
+ uint32_t node_id;
+ int32_t parent_node_id;
+ uint32_t priority;
+ uint32_t weight;
+ uint32_t level_id;
+ int32_t shaper_profile_id;
+ uint32_t n_sp_priorities;
+ uint64_t stats_mask;
+ cmdline_multi_string_t multi_shared_shaper_id;
+};
+
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_pmode_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_pmode_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result, port, "port");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_pmode_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result, tm, "tm");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_pmode_nonleaf =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result, nonleaf, "nonleaf");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_pmode_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result, node, "node");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_pmode_pktmode =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result, node, "pktmode");
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ node_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_parent_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ parent_node_id, INT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ priority, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_weight =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ weight, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_level_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ level_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_shaper_profile_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ shaper_profile_id, INT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_n_sp_priorities =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ n_sp_priorities, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_pmode_stats_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ stats_mask, UINT64);
+cmdline_parse_token_string_t
+ cmd_add_port_tm_nonleaf_node_pmode_multi_shrd_shpr_id =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_pmode_result,
+ multi_shared_shaper_id, TOKEN_STRING_MULTI);
+
+static void cmd_add_port_tm_nonleaf_node_pmode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_add_port_tm_nonleaf_node_pmode_result *res = parsed_result;
+ uint32_t parent_node_id, n_shared_shapers = 0;
+ char *s_str = res->multi_shared_shaper_id;
+ portid_t port_id = res->port_id;
+ struct rte_tm_node_params np;
+ int *wfq_weight_mode = NULL;
+ uint32_t *shared_shaper_id;
+ struct rte_tm_error error;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&np, 0, sizeof(struct rte_tm_node_params));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+
+ /* Node parameters */
+ if (res->parent_node_id < 0)
+ parent_node_id = UINT32_MAX;
+ else
+ parent_node_id = res->parent_node_id;
+
+ shared_shaper_id = (uint32_t *)malloc(MAX_NUM_SHARED_SHAPERS *
+ sizeof(uint32_t));
+ if (shared_shaper_id == NULL) {
+ printf(" Memory not allocated for shared shapers (error)\n");
+ return;
+ }
+
+ /* Parse multi shared shaper id string */
+ ret = parse_multi_ss_id_str(s_str, &n_shared_shapers, shared_shaper_id);
+ if (ret) {
+ printf(" Shared shapers params string parse error\n");
+ free(shared_shaper_id);
+ return;
+ }
+
+ if (res->shaper_profile_id < 0)
+ np.shaper_profile_id = UINT32_MAX;
+ else
+ np.shaper_profile_id = res->shaper_profile_id;
+
+ np.n_shared_shapers = n_shared_shapers;
+ if (np.n_shared_shapers) {
+ np.shared_shaper_id = &shared_shaper_id[0];
+ } else {
+ free(shared_shaper_id);
+ shared_shaper_id = NULL;
+ }
+
+ if (res->n_sp_priorities)
+ wfq_weight_mode = calloc(res->n_sp_priorities, sizeof(int));
+ np.nonleaf.n_sp_priorities = res->n_sp_priorities;
+ np.stats_mask = res->stats_mask;
+ np.nonleaf.wfq_weight_mode = wfq_weight_mode;
+
+ ret = rte_tm_node_add(port_id, res->node_id, parent_node_id,
+ res->priority, res->weight, res->level_id,
+ &np, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ free(shared_shaper_id);
+ free(wfq_weight_mode);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_tm_nonleaf_node_pmode = {
+ .f = cmd_add_port_tm_nonleaf_node_pmode_parsed,
+ .data = NULL,
+ .help_str = "Add port tm nonleaf node pktmode",
+ .tokens = {
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_add,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_port,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_tm,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_nonleaf,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_node,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_pktmode,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_port_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_node_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_parent_node_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_priority,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_weight,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_level_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_shaper_profile_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_n_sp_priorities,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_stats_mask,
+ (void *)&cmd_add_port_tm_nonleaf_node_pmode_multi_shrd_shpr_id,
+ NULL,
+ },
+};
/* *** Add Port TM leaf node *** */
struct cmd_add_port_tm_leaf_node_result {
cmdline_fixed_string_t add;
diff --git a/app/test-pmd/cmdline_tm.h b/app/test-pmd/cmdline_tm.h
index 950cb75..e59c15c 100644
--- a/app/test-pmd/cmdline_tm.h
+++ b/app/test-pmd/cmdline_tm.h
@@ -19,6 +19,7 @@ extern cmdline_parse_inst_t cmd_add_port_tm_node_wred_profile;
extern cmdline_parse_inst_t cmd_del_port_tm_node_wred_profile;
extern cmdline_parse_inst_t cmd_set_port_tm_node_shaper_profile;
extern cmdline_parse_inst_t cmd_add_port_tm_nonleaf_node;
+extern cmdline_parse_inst_t cmd_add_port_tm_nonleaf_node_pmode;
extern cmdline_parse_inst_t cmd_add_port_tm_leaf_node;
extern cmdline_parse_inst_t cmd_del_port_tm_node;
extern cmdline_parse_inst_t cmd_set_port_tm_node_parent;
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5bb12a5..9072ed6 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2971,6 +2971,33 @@ where:
* ``n_shared_shapers``: Number of shared shapers.
* ``shared_shaper_id``: Shared shaper id.
+Add port traffic management hierarchy nonleaf node with packet mode
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add nonleaf node with packet mode to port traffic management hierarchy::
+
+ testpmd> add port tm nonleaf node pktmode (port_id) (node_id) (parent_node_id) \
+ (priority) (weight) (level_id) (shaper_profile_id) \
+ (n_sp_priorities) (stats_mask) (n_shared_shapers) \
+ [(shared_shaper_0) (shared_shaper_1) ...] \
+
+where:
+
+* ``parent_node_id``: Node ID of the parent.
+* ``priority``: Node priority (highest node priority is zero). This is used by
+ the SP algorithm running on the parent node for scheduling this node.
+* ``weight``: Node weight (lowest weight is one). The node weight is relative
+ to the weight sum of all siblings that have the same priority. It is used by
+ the WFQ algorithm running on the parent node for scheduling this node.
+* ``level_id``: Hierarchy level of the node.
+* ``shaper_profile_id``: Shaper profile ID of the private shaper to be used by
+ the node.
+* ``n_sp_priorities``: Number of strict priorities. Packet mode is enabled on
+ all of them.
+* ``stats_mask``: Mask of statistics counter types to be enabled for this node.
+* ``n_shared_shapers``: Number of shared shapers.
+* ``shared_shaper_id``: Shared shaper id.
+
Add port traffic management hierarchy leaf node
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.8.4
next prev parent reply other threads:[~2020-03-30 16:00 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-30 16:00 [dpdk-dev] [PATCH 1/2] ethdev: add tm cap for private shaper packet mode Nithin Dabilpuram
2020-03-30 16:00 ` Nithin Dabilpuram [this message]
2020-04-07 7:30 ` Nithin Dabilpuram
2020-04-07 16:31 ` Dumitrescu, Cristian
2020-04-07 17:21 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-04-10 11:45 ` Dumitrescu, Cristian
2020-04-10 11:56 ` Nithin Dabilpuram
2020-04-11 11:44 ` [dpdk-dev] [PATCH v2 1/4] ethdev: add tm support for shaper config in pkt mode Nithin Dabilpuram
2020-04-11 11:44 ` [dpdk-dev] [PATCH v2 2/4] drivers/net: update tm capability for existing pmds Nithin Dabilpuram
2020-04-11 11:44 ` [dpdk-dev] [PATCH v2 3/4] app/testpmd: add tm cmd for non leaf and shaper pktmode Nithin Dabilpuram
2020-04-11 11:44 ` [dpdk-dev] [PATCH v2 4/4] net/octeontx2: support tm length adjust and pkt mode Nithin Dabilpuram
2020-04-16 13:48 ` [dpdk-dev] [PATCH v2 1/4] ethdev: add tm support for shaper config in " Ferruh Yigit
2020-04-21 5:11 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-04-21 9:30 ` [dpdk-dev] " Dumitrescu, Cristian
2020-04-21 9:58 ` Nithin Dabilpuram
2020-04-21 10:23 ` Dumitrescu, Cristian
2020-04-21 11:55 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-04-22 7:59 ` [dpdk-dev] [PATCH v3] " Nithin Dabilpuram
2020-04-22 7:59 ` [dpdk-dev] [PATCH v3 2/4] drivers/net: update tm capability for existing pmds Nithin Dabilpuram
2020-04-22 7:59 ` [dpdk-dev] [PATCH v3 3/4] app/testpmd: add tm cmd for non leaf and shaper pktmode Nithin Dabilpuram
2020-04-22 7:59 ` [dpdk-dev] [PATCH v3 4/4] net/octeontx2: support tm length adjust and pkt mode Nithin Dabilpuram
2020-04-22 8:09 ` [dpdk-dev] [PATCH v3] ethdev: add tm support for shaper config in " Nithin Dabilpuram
2020-04-22 12:18 ` Singh, Jasvinder
2020-04-22 17:21 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-04-22 10:10 ` [dpdk-dev] " Dumitrescu, Cristian
2020-04-22 11:31 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-04-22 11:49 ` Nithin Dabilpuram
2020-04-22 11:59 ` Dumitrescu, Cristian
2020-04-22 12:01 ` Dumitrescu, Cristian
2020-04-22 8:05 ` [dpdk-dev] [PATCH v3 1/4] " Nithin Dabilpuram
2020-04-22 17:21 ` [dpdk-dev] [PATCH v4 " Nithin Dabilpuram
2020-04-22 17:21 ` [dpdk-dev] [PATCH v4 2/4] drivers/net: update tm capability for existing pmds Nithin Dabilpuram
2020-04-22 17:21 ` [dpdk-dev] [PATCH v4 3/4] app/testpmd: add tm cmd for non leaf and shaper pktmode Nithin Dabilpuram
2020-04-22 17:21 ` [dpdk-dev] [PATCH v4 4/4] net/octeontx2: support tm length adjust and pkt mode Nithin Dabilpuram
2020-04-24 10:28 ` [dpdk-dev] [PATCH v4 1/4] ethdev: add tm support for shaper config in " Dumitrescu, Cristian
2020-04-25 20:09 ` Ferruh Yigit
2020-04-27 9:19 ` Dumitrescu, Cristian
2020-04-27 16:12 ` Ferruh Yigit
2020-04-27 16:28 ` Dumitrescu, Cristian
2020-04-28 15:30 ` Thomas Monjalon
2020-04-28 17:35 ` Dumitrescu, Cristian
2020-04-27 16:29 ` Jerin Jacob
2020-04-27 16:49 ` Ferruh Yigit
2020-04-27 16:59 ` Jerin Jacob
2020-04-28 11:51 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-04-28 13:56 ` Ferruh Yigit
2020-04-28 14:06 ` [dpdk-dev] " Ferruh Yigit
2020-04-28 14:45 ` Bruce Richardson
2020-04-28 15:04 ` Luca Boccassi
2020-04-28 15:54 ` Thomas Monjalon
2020-04-29 8:45 ` Dumitrescu, Cristian
2020-04-29 9:03 ` Bruce Richardson
2020-05-01 10:27 ` Ferruh Yigit
2020-05-01 13:16 ` [dpdk-dev] [EXT] " Nithin Dabilpuram
2020-08-25 16:59 ` Ferruh Yigit
2020-09-07 11:12 ` Nithin Dabilpuram
2020-09-14 13:01 ` Ferruh Yigit
2020-05-01 13:18 ` [dpdk-dev] " Jerin Jacob
2020-05-05 8:01 ` Ray Kinsella
2020-04-28 15:42 ` Ray Kinsella
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=20200330160019.29674-2-ndabilpuram@marvell.com \
--to=ndabilpuram@marvell.com \
--cc=bernard.iremonger@intel.com \
--cc=dev@dpdk.org \
--cc=jerinj@marvell.com \
--cc=jingjing.wu@intel.com \
--cc=john.mcnamara@intel.com \
--cc=kkanas@marvell.com \
--cc=marko.kovacevic@intel.com \
--cc=wenzhuo.lu@intel.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).