Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
From: Sasha Khapyorsky <sashak-smomgflXvOZWk0Htik3J/w@public.gmane.org>
To: Ralph Campbell <ralph.campbell-h88ZbnxC6KDQT0dZR+AlfA@public.gmane.org>
Cc: linux-rdma <linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [PATCH] infiniband-diags/ibportstate: allow changes to CA portinfo parameters
Date: Tue, 1 Dec 2009 05:17:22 +0200	[thread overview]
Message-ID: <20091201031722.GI16607@me> (raw)
In-Reply-To: <1257451016.992.173.camel-/vjeY7uYZjrPXfVEPVhPGq6RkeBMCJyt@public.gmane.org>

Hi Ralph,

On 11:56 Thu 05 Nov     , Ralph Campbell wrote:
> This patch adds new commands to ibportstate to support initializing
> the link for CAs connected back-to-back. It also allows more than
> one field to be changed at the same time such as "lid 23 arm" or
> "width 1 speed 3 enable".

As far as I can see this changes a functionality of ibportstate
dramatically. Actually it makes it more like to 'ibportset' than just
'ibportstate', correct?

If so, wouldn't it be better to introduce a new tool - let's say
'ibportset' (or like this)?

(Or even wider 'smpset' - however such 'smpset' can be done later
following a real needs by extending ibportset or so).

Don't understand me wrong I'm not disagree at all, just trying to find
the best way to add such functionality to infiniband-diags.

Sasha

> 
> Signed-off-by: Ralph Campbell <ralph.campbell-h88ZbnxC6KDQT0dZR+AlfA@public.gmane.org>
> ---
> 
> diff --git a/infiniband-diags/src/ibportstate.c b/infiniband-diags/src/ibportstate.c
> index e631bfd..192b14e 100644
> --- a/infiniband-diags/src/ibportstate.c
> +++ b/infiniband-diags/src/ibportstate.c
> @@ -46,93 +46,133 @@
>  
>  #include "ibdiag_common.h"
>  
> +enum port_ops {
> +	QUERY,
> +	ENABLE,
> +	RESET,
> +	DISABLE,
> +	SPEED,
> +	WIDTH,
> +	DOWN,
> +	ARM,
> +	ACTIVE,
> +	VLS,
> +	MTU,
> +	LID,
> +	SMLID,
> +	LMC,
> +};
> +
>  struct ibmad_port *srcport;
> +int speed = 15;
> +int width = 255;
> +int lid;
> +int smlid;
> +int lmc;
> +int mtu;
> +int vls;
> +
> +struct {
> +	const char *name;
> +	int *val;
> +	int set;
> +} port_args[] = {
> +	{ "query", NULL, 0 },	/* QUERY */
> +	{ "enable", NULL, 0 },	/* ENABLE */
> +	{ "reset", NULL, 0 },	/* RESET */
> +	{ "disable", NULL, 0 },	/* DISABLE */
> +	{ "speed", &speed, 0 },	/* SPEED */
> +	{ "width", &width, 0 },	/* WIDTH */
> +	{ "down", NULL, 0 },	/* DOWN */
> +	{ "arm", NULL, 0 },	/* ARM */
> +	{ "active", NULL, 0 },	/* ACTIVE */
> +	{ "vls", &vls, 0 },	/* VLS */
> +	{ "mtu", &mtu, 0 },	/* MTU */
> +	{ "lid", &lid, 0 },	/* LID */
> +	{ "smlid", &smlid, 0 },	/* SMLID */
> +	{ "lmc", &lmc, 0 },	/* LMC */
> +};
> +
> +#define NPORT_ARGS (sizeof(port_args) / sizeof(port_args[0]))
>  
>  /*******************************************/
>  
> +/*
> + * Return 1 if port is a switch, else zero.
> + */
>  static int get_node_info(ib_portid_t * dest, uint8_t * data)
>  {
>  	int node_type;
>  
>  	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
> -		return -1;
> +		IBERROR("smp query nodeinfo failed");
>  
>  	node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
>  	if (node_type == IB_NODE_SWITCH)	/* Switch NodeType ? */
> -		return 0;
> -	else
>  		return 1;
> +	else
> +		return 0;
>  }
>  
> -static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
> -			 int port_op)
> +static void get_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
> +{
> +	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
> +		IBERROR("smp query portinfo failed");
> +}
> +
> +static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
>  {
>  	char buf[2048];
>  	char val[64];
>  
> -	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
> -		return -1;
> -
> -	if (port_op != 4) {
> -		mad_dump_portstates(buf, sizeof buf, data, sizeof data);
> -		mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
> -		mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F,
> -			       buf + strlen(buf), sizeof buf - strlen(buf),
> -			       val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -		mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
> -		mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
> -			       sizeof buf - strlen(buf), val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -		mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
> -		mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
> -			       sizeof buf - strlen(buf), val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -		mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
> -		mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F,
> -			       buf + strlen(buf), sizeof buf - strlen(buf),
> -			       val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -		mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
> -		mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
> -			       sizeof buf - strlen(buf), val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -		mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
> -		mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
> -			       sizeof buf - strlen(buf), val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -	} else {
> -		mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
> -		mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf,
> -			       val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -	}
> +	mad_dump_portstates(buf, sizeof buf, data, sizeof data);
> +	mad_decode_field(data, IB_PORT_LID_F, val);
> +	mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_SMLID_F, val);
> +	mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LMC_F, val);
> +	mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
> +	mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
> +	mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
> +	mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
> +	mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
> +	mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
> +	mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
> +	mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
> +		       sizeof buf - strlen(buf), val);
> +	sprintf(buf + strlen(buf), "%s", "\n");
>  
>  	printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
> -	return 0;
>  }
>  
> -static int set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
> -			 int port_op)
> +static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
>  {
> -	char buf[2048];
> -	char val[64];
> -
>  	if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
> -		return -1;
> -
> -	if (port_op != 4)
> -		mad_dump_portstates(buf, sizeof buf, data, sizeof data);
> -	else {
> -		mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
> -		mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf,
> -			       val);
> -		sprintf(buf + strlen(buf), "%s", "\n");
> -	}
> +		IBERROR("smp set portinfo failed");
>  
>  	printf("\nAfter PortInfo set:\n");
> -	printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
> -	return 0;
> +	show_port_info(dest, data, portnum);
>  }
>  
>  static int get_link_width(int lwe, int lws)
> @@ -201,22 +241,23 @@ int main(int argc, char **argv)
>  	int mgmt_classes[3] =
>  	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
>  	ib_portid_t portid = { 0 };
> -	int err;
> -	int port_op = 0;	/* default to query */
> -	int speed = 15;
> -	int is_switch = 1;
> +	int port_op = -1;
> +	int is_switch;
>  	int state, physstate, lwe, lws, lwa, lse, lss, lsa;
>  	int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
>  	    peerlsa;
> -	int width = 255, peerwidth, peerspeed;
> +	int peerwidth, peerspeed;
>  	uint8_t data[IB_SMP_DATA_SIZE];
>  	ib_portid_t peerportid = { 0 };
>  	int portnum = 0;
>  	ib_portid_t selfportid = { 0 };
>  	int selfport = 0;
> -
> +	int changed = 0;
> +	int i;
> +	long val;
>  	char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
> -	    "\nSupported ops: enable, disable, reset, speed, width, query";
> +	    "\nSupported ops: enable, disable, reset, speed, width, query,\n"
> +	    "\tdown, arm, active, vls, mtu, lid, smlid, lmc\n";
>  	const char *usage_examples[] = {
>  		"3 1 disable\t\t\t# by lid",
>  		"-G 0x2C9000100D051 1 enable\t# by guid",
> @@ -224,6 +265,7 @@ int main(int argc, char **argv)
>  		"3 1 reset\t\t\t# by lid",
>  		"3 1 speed 1\t\t\t# by lid",
>  		"3 1 width 1\t\t\t# by lid",
> +		"-D 0 1 lid 0x1234 arm\t\t# by direct route",
>  		NULL
>  	};
>  
> @@ -247,78 +289,130 @@ int main(int argc, char **argv)
>  	if (argc > 1)
>  		portnum = strtol(argv[1], 0, 0);
>  
> -	/* First, make sure it is a switch port if it is a "set" */
> -	if (argc >= 3) {
> -		if (!strcmp(argv[2], "enable"))
> -			port_op = 1;
> -		else if (!strcmp(argv[2], "disable"))
> -			port_op = 2;
> -		else if (!strcmp(argv[2], "reset"))
> -			port_op = 3;
> -		else if (!strcmp(argv[2], "speed")) {
> -			if (argc < 4)
> -				IBERROR
> -				    ("speed requires an additional parameter");
> -			port_op = 4;
> -			/* Parse speed value */
> -			speed = strtoul(argv[3], 0, 0);
> -			if (speed > 15)
> -				IBERROR("invalid speed value %d", speed);
> -		} else if (!strcmp(argv[2], "width")) {
> -			if (argc < 4)
> -				IBERROR
> -				    ("width requires an additional parameter");
> -			port_op = 5;
> -			/* Parse width value */
> -			width = strtoul(argv[3], 0, 0);
> -			if (width > 15 && width != 255)
> -				IBERROR("invalid width value %d", width);
> +	for (i = 2; i < argc; i++) {
> +		int j;
> +
> +		for (j = 0; j < NPORT_ARGS; j++) {
> +			if (strcmp(argv[i], port_args[j].name))
> +				continue;
> +			port_args[j].set = 1;
> +			if (!port_args[j].val) {
> +				if (port_op >= 0)
> +					IBERROR("%s only one of: ",
> +						"query, enable, disable, "
> +						"reset, down, arm, active, "
> +						"can be specified",
> +						port_args[j].name);
> +				port_op = j;
> +				break;
> +			}
> +			if (++i >= argc)
> +				IBERROR("%s requires an additional parameter",
> +					port_args[j].name);
> +			val = strtol(argv[i], 0, 0);
> +			switch (j) {
> +			case SPEED:
> +				if (val < 0 || val > 15)
> +					IBERROR("invalid speed value %ld", val);
> +				break;
> +			case WIDTH:
> +				if (val < 0 || (val > 15 && val != 255))
> +					IBERROR("invalid width value %ld", val);
> +				break;
> +			case VLS:
> +				if (val <= 0 || val > 5)
> +					IBERROR("invalid vls value %ld", val);
> +				break;
> +			case MTU:
> +				if (val <= 0 || val > 5)
> +					IBERROR("invalid mtu value %ld", val);
> +				break;
> +			case LID:
> +				if (val <= 0 || val >= 0xC000)
> +					IBERROR("invalid lid value 0x%lx", val);
> +				break;
> +			case SMLID:
> +				if (val <= 0 || val >= 0xC000)
> +					IBERROR("invalid smlid value 0x%lx",
> +						val);
> +				break;
> +			case LMC:
> +				if (val < 0 || val > 7)
> +					IBERROR("invalid lmc value %ld", val);
> +			}
> +			*port_args[j].val = (int) val;
> +			changed = 1;
> +			break;
>  		}
> +		if (j == NPORT_ARGS)
> +			IBERROR("invalid operation: %s", argv[i]);
>  	}
> +	if (port_op < 0)
> +		port_op = QUERY;
>  
> -	err = get_node_info(&portid, data);
> -	if (err < 0)
> -		IBERROR("smp query nodeinfo failed");
> -	if (err) {		/* not switch */
> -		if (port_op == 0)	/* query op */
> -			is_switch = 0;
> -		else if (port_op == 2)	/* disable */
> -			IBERROR("Node type not switch - disable not allowed");
> -	}
> +	is_switch = get_node_info(&portid, data);
>  
> -	if (port_op)
> -		printf("Initial PortInfo:\n");
> +	if (port_op != QUERY || changed)
> +		printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA");
>  	else
> -		printf("PortInfo:\n");
> -	err = get_port_info(&portid, data, portnum, port_op);
> -	if (err < 0)
> -		IBERROR("smp query portinfo failed");
> -
> -	/* Only if one of the "set" options is chosen */
> -	if (port_op) {
> -		if ((port_op == 1) || (port_op == 3)) {	/* Enable or Reset port */
> -			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);	/* Polling */
> -			mad_set_field(data, 0, IB_PORT_STATE_F, 0);	/* No Change */
> -		} else if (port_op == 2) {	/* Disable port */
> +		printf("%s PortInfo:\n", is_switch ? "Switch" : "CA");
> +	get_port_info(&portid, data, portnum);
> +	show_port_info(&portid, data, portnum);
> +
> +	if (port_op != QUERY || changed) {
> +		/*
> +		 * If we aren't setting the LID and the LID is the default,
> +		 * the SMA command will fail due to an invalid LID.
> +		 * Set it to something unlikely but valid.
> +		 */
> +		val = mad_get_field(data, 0, IB_PORT_LID_F);
> +		if (!port_args[LID].set && (!val || val == 0xFFFF))
> +			mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
> +		val = mad_get_field(data, 0, IB_PORT_SMLID_F);
> +		if (!port_args[SMLID].set && (!val || val == 0xFFFF))
> +			mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
> +		mad_set_field(data, 0, IB_PORT_STATE_F, 0);       /* NOP */
> +		mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);  /* NOP */
> +
> +		switch (port_op) {
> +		case ENABLE:
> +		case RESET:
> +			/* Polling */
> +			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
> +			break;
> +		case DISABLE:
>  			printf("Disable may be irreversible\n");
> -			mad_set_field(data, 0, IB_PORT_STATE_F, 1);	/* Down */
> -			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);	/* Disabled */
> -		} else if (port_op == 4) {	/* Set speed */
> +			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
> +			break;
> +		case DOWN:
> +			mad_set_field(data, 0, IB_PORT_STATE_F, 1);
> +			break;
> +		case ARM:
> +			mad_set_field(data, 0, IB_PORT_STATE_F, 3);
> +			break;
> +		case ACTIVE:
> +			mad_set_field(data, 0, IB_PORT_STATE_F, 4);
> +			break;
> +		}
> +		if (port_args[SPEED].set)
>  			mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F,
>  				      speed);
> -			mad_set_field(data, 0, IB_PORT_STATE_F, 0);
> -			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);
> -		} else if (port_op == 5) {	/* Set width */
> +		if (port_args[WIDTH].set)
>  			mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F,
>  				      width);
> -			mad_set_field(data, 0, IB_PORT_STATE_F, 0);
> -			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);
> -		}
> +		if (port_args[VLS].set)
> +			mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
> +		if (port_args[MTU].set)
> +			mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
> +		if (port_args[LID].set)
> +			mad_set_field(data, 0, IB_PORT_LID_F, lid);
> +		if (port_args[SMLID].set)
> +			mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
> +		if (port_args[LMC].set)
> +			mad_set_field(data, 0, IB_PORT_LMC_F, lmc);
> +
> +		set_port_info(&portid, data, portnum);
>  
> -		err = set_port_info(&portid, data, portnum, port_op);
> -		if (err < 0)
> -			IBERROR("smp set portinfo failed");
> -		/* query op - only compare peer port if switch port, exclude SP0 */
>  	} else if (is_switch && portnum) {
>  		/* Now, make sure PortState is Active */
>  		/* Or is PortPhysicalState LinkUp sufficient ? */
> @@ -351,20 +445,15 @@ int main(int argc, char **argv)
>  			peerportid.drpath.drdlid = 0xffff;
>  
>  			/* Get peer port NodeInfo to obtain peer port number */
> -			err = get_node_info(&peerportid, data);
> -			if (err < 0)
> -				IBERROR("smp query nodeinfo failed");
> +			get_node_info(&peerportid, data);
>  
>  			mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
>  					 &peerlocalportnum);
>  
>  			printf("Peer PortInfo:\n");
>  			/* Get peer port characteristics */
> -			err =
> -			    get_port_info(&peerportid, data, peerlocalportnum,
> -					  port_op);
> -			if (err < 0)
> -				IBERROR("smp query peer portinfo failed");
> +			get_port_info(&peerportid, data, peerlocalportnum);
> +			show_port_info(&peerportid, data, peerlocalportnum);
>  
>  			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
>  					 &peerlwe);
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2009-12-01  3:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-05 19:56 [PATCH] infiniband-diags/ibportstate: allow changes to CA portinfo parameters Ralph Campbell
     [not found] ` <1257451016.992.173.camel-/vjeY7uYZjrPXfVEPVhPGq6RkeBMCJyt@public.gmane.org>
2009-12-01  3:17   ` Sasha Khapyorsky [this message]
2009-12-01 17:27     ` Ralph Campbell
2009-12-01 18:09     ` Ira Weiny
2010-01-11 21:43   ` Ralph Campbell
     [not found]     ` <1263246218.3077.75.camel-/vjeY7uYZjrPXfVEPVhPGq6RkeBMCJyt@public.gmane.org>
2010-01-12 10:11       ` Sasha Khapyorsky
2010-01-13 20:16         ` Hal Rosenstock
2010-01-12 10:14   ` Sasha Khapyorsky

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=20091201031722.GI16607@me \
    --to=sashak-smomgflxvozwk0htik3j/w@public.gmane.org \
    --cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=ralph.campbell-h88ZbnxC6KDQT0dZR+AlfA@public.gmane.org \
    /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