All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 ethtool 1/2] ethtool: Support for configurable RSS hash key
       [not found] <1393589444-10721-1-git-send-email-VenkatKumar.Duvvuru@Emulex.com>
@ 2014-02-28 12:10 ` Venkat Duvvuru
  2014-02-28 12:10 ` [PATCH v3 ethtool 2/2] " Venkat Duvvuru
  1 sibling, 0 replies; 2+ messages in thread
From: Venkat Duvvuru @ 2014-02-28 12:10 UTC (permalink / raw)
  To: netdev; +Cc: Venkat Duvvuru

This ethtool patch adds new structure ethtool_rxfh definition for ETHTOOL_GRSSH
and ETHTOOL_SRSSH commands.

Kernel tree: net-next
---
 ethtool-copy.h |   33 +++++++++++++++++++++++++++++++--
 1 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index b5515c2..7c12af1 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -628,6 +628,32 @@ struct ethtool_rxfh_indir {
 	__u32	size;
 	__u32	ring_index[0];
 };
+/**
+ * struct ethtool_rxfh - command to get or set RX flow hash indirection or/and
+ * hash key.
+ * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
+ * @indir_size: On entry, the array size of the user buffer, which may be zero.
+ *		On return from %ETHTOOL_GRSSH, the array size of the hardware
+ *		indirection table.
+ * @key_size:	On entry, the array size of the user buffer in bytes,
+ *		which may be zero.
+ *		On return from %ETHTOOL_GRSSH, the size of the RSS hash key.
+ * @rsvd:	Reserved for future extensions.
+ * @rss_config: RX ring/queue index for each hash value or/and hash key
+ *		respectively.
+ *
+ * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the
+ * size should be returned.  For %ETHTOOL_SRSSH, a @indir_size of zero means
+ * the indir table should be reset to default values.  This last feature
+ * is not supported by the original implementations.
+ */
+struct ethtool_rxfh {
+	__u32   cmd;
+	__u32   indir_size;
+	__u32   key_size;
+	__u32	rsvd[3];
+	__u32   rss_config[0];
+};
 
 /**
  * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
@@ -901,6 +927,9 @@ enum ethtool_sfeatures_retval_bits {
 #define ETHTOOL_GEEE		0x00000044 /* Get EEE settings */
 #define ETHTOOL_SEEE		0x00000045 /* Set EEE settings */
 
+#define ETHTOOL_GRSSH		0x00000046 /* Get RX flow hash configuration */
+#define ETHTOOL_SRSSH		0x00000047 /* Set RX flow hash configuration */
+
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
 #define SPARC_ETH_SSET		ETHTOOL_SSET
@@ -993,8 +1022,8 @@ enum ethtool_sfeatures_retval_bits {
 #define PORT_OTHER		0xff
 
 /* Which transceiver to use. */
-#define XCVR_INTERNAL		0x00
-#define XCVR_EXTERNAL		0x01
+#define XCVR_INTERNAL		0x00 /* PHY and MAC are in the same package */
+#define XCVR_EXTERNAL		0x01 /* PHY and MAC are in different packages */
 #define XCVR_DUMMY1		0x02
 #define XCVR_DUMMY2		0x03
 #define XCVR_DUMMY3		0x04
-- 
1.7.1

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

* [PATCH v3 ethtool 2/2] ethtool: Support for configurable RSS hash key
       [not found] <1393589444-10721-1-git-send-email-VenkatKumar.Duvvuru@Emulex.com>
  2014-02-28 12:10 ` [PATCH v3 ethtool 1/2] ethtool: Support for configurable RSS hash key Venkat Duvvuru
@ 2014-02-28 12:10 ` Venkat Duvvuru
  1 sibling, 0 replies; 2+ messages in thread
From: Venkat Duvvuru @ 2014-02-28 12:10 UTC (permalink / raw)
  To: netdev; +Cc: Venkat Duvvuru

This ethtool patch will primarily implement the parser for the options provided
by the user for set and get rxfh before invoking the ioctl.
This patch also has Ethtool man page changes which describes the Usage of
set and get rxfh options.
---
 ethtool.8.in |   18 +++--
 ethtool.c    |  253 ++++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 212 insertions(+), 59 deletions(-)

diff --git a/ethtool.8.in b/ethtool.8.in
index bb394cc..df5a6ce 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -286,11 +286,12 @@ ethtool \- query or control network driver and hardware settings
 .B ethtool \-T|\-\-show\-time\-stamping
 .I devname
 .HP
-.B ethtool \-x|\-\-show\-rxfh\-indir
+.B ethtool \-x|\-\-show\-rxfh\-indir|\-\-show\-rxfh
 .I devname
 .HP
-.B ethtool \-X|\-\-set\-rxfh\-indir
+.B ethtool \-X|\-\-set\-rxfh\-indir|\-\-rxfh
 .I devname
+.RB [ hkey \ \*(MA:\...]
 .RB [\  equal
 .IR N \ |
 .BI weight\  W0
@@ -784,11 +785,16 @@ Sets the dump flag for the device.
 Show the device's time stamping capabilities and associated PTP
 hardware clock.
 .TP
-.B \-x \-\-show\-rxfh\-indir
-Retrieves the receive flow hash indirection table.
+.B \-x \-\-show\-rxfh\-indir \-\-show\-rxfh
+Retrieves the receive flow hash indirection table and/or RSS hash key.
 .TP
-.B \-X \-\-set\-rxfh\-indir
-Configures the receive flow hash indirection table.
+.B \-X \-\-set\-rxfh\-indir \-\-rxfh
+Configures the receive flow hash indirection table and/or RSS hash key.
+.TP
+.BI hkey
+Sets rss hash key of the specified network device. RSS hash key should be of device supported length.
+Hash key format must be in xx:yy:zz:aa:bb:cc format meaning both the nibbles of a byte should be mentioned
+even if a nibble is zero.
 .TP
 .BI equal\  N
 Sets the receive flow hash indirection table to spread flows evenly
diff --git a/ethtool.c b/ethtool.c
index acb4397..0791451 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -874,6 +874,73 @@ static char *unparse_rxfhashopts(u64 opts)
 	return buf;
 }
 
+static int convert_string_to_hashkey(char *rss_hkey, u32 key_size,
+				     const char *rss_hkey_string)
+{
+	int i = 0;
+	int hex_byte;
+
+	do {
+		if (i > (key_size - 1)) {
+			fprintf(stderr,
+				"Invalid key: Device supports %d bytes key\n",
+				key_size);
+			goto err;
+		}
+
+		if (!(isxdigit(*rss_hkey_string) &&
+		      isxdigit(*(rss_hkey_string + 1)))) {
+			fprintf(stderr, "Invalid RSS Hash Key Format\n");
+			goto err;
+		}
+
+		sscanf(rss_hkey_string, "%2x", &hex_byte);
+		rss_hkey[i++] = hex_byte;
+		rss_hkey_string += 2;
+
+		if (*rss_hkey_string == ':') {
+			rss_hkey_string++;
+		} else if (*rss_hkey_string != '\0') {
+			fprintf(stderr, "Invalid RSS Hash Key Format\n");
+			goto err;
+		}
+
+	} while (*rss_hkey_string);
+
+	if (i != key_size) {
+		fprintf(stderr, "Invalid key: Device supports %d bytes key\n",
+			key_size);
+		goto err;
+	}
+
+	return 0;
+err:
+	exit_bad_args();
+}
+
+static int parse_hkey(char **rss_hkey, u32 key_size,
+		      const char *rss_hkey_string)
+{
+	if (!key_size) {
+		fprintf(stderr,
+			"Cannot set RX flow hash configuration:\n"
+			" Hash key setting not supported\n");
+		exit(1);
+	}
+
+	*rss_hkey = malloc(key_size);
+	if (!(*rss_hkey))
+		return -ENOMEM;
+
+	if (convert_string_to_hashkey(*rss_hkey, key_size,
+				      rss_hkey_string) < 0) {
+		free(*rss_hkey);
+		*rss_hkey = NULL;
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static const struct {
 	const char *name;
 	int (*func)(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
@@ -3035,13 +3102,14 @@ static int do_grxclass(struct cmd_context *ctx)
 	return err ? 1 : 0;
 }
 
-static int do_grxfhindir(struct cmd_context *ctx)
+static int do_grxfh(struct cmd_context *ctx)
 {
 	struct ethtool_rxnfc ring_count;
-	struct ethtool_rxfh_indir indir_head;
-	struct ethtool_rxfh_indir *indir;
-	u32 i;
+	struct ethtool_rxfh rss_head;
+	struct ethtool_rxfh *rss;
+	u32 i, indir_bytes;
 	int err;
+	char *hkey;
 
 	ring_count.cmd = ETHTOOL_GRXRINGS;
 	err = send_ioctl(ctx, &ring_count);
@@ -3050,77 +3118,146 @@ static int do_grxfhindir(struct cmd_context *ctx)
 		return 102;
 	}
 
-	indir_head.cmd = ETHTOOL_GRXFHINDIR;
-	indir_head.size = 0;
-	err = send_ioctl(ctx, &indir_head);
-	if (err < 0) {
-		perror("Cannot get RX flow hash indirection table size");
+	rss_head.cmd = ETHTOOL_GRSSH;
+	rss_head.indir_size = 0;
+	rss_head.key_size = 0;
+	err = send_ioctl(ctx, &rss_head);
+	if ((err < 0) || (!rss_head.indir_size && !rss_head.key_size)) {
+		perror("Cannot get RX flow hash indirection and key size");
 		return 103;
 	}
 
-	indir = malloc(sizeof(*indir) +
-		       indir_head.size * sizeof(*indir->ring_index));
-	indir->cmd = ETHTOOL_GRXFHINDIR;
-	indir->size = indir_head.size;
-	err = send_ioctl(ctx, indir);
+	rss = malloc(sizeof(*rss) +
+		     rss_head.indir_size * sizeof(rss_head.rss_config[0]) +
+		     rss_head.key_size);
+	rss->cmd = ETHTOOL_GRSSH;
+	rss->indir_size = rss_head.indir_size;
+	rss->key_size = rss_head.key_size;
+	err = send_ioctl(ctx, rss);
 	if (err < 0) {
-		perror("Cannot get RX flow hash indirection table");
+		perror("Cannot get RX flow hash configuration");
 		return 103;
 	}
 
 	printf("RX flow hash indirection table for %s with %llu RX ring(s):\n",
 	       ctx->devname, ring_count.data);
-	for (i = 0; i < indir->size; i++) {
+	if (!rss->indir_size)
+		printf("*** Operation Not Supported ***\n");
+
+	for (i = 0; i < rss->indir_size; i++) {
 		if (i % 8 == 0)
 			printf("%5u: ", i);
-		printf(" %5u", indir->ring_index[i]);
+		printf(" %5u", rss->rss_config[i]);
 		if (i % 8 == 7)
 			fputc('\n', stdout);
 	}
+
+	indir_bytes = rss->indir_size * sizeof(rss->rss_config[0]);
+	hkey = ((char *)rss->rss_config + indir_bytes);
+
+	printf("RSS hash key:\n");
+	if (!rss->key_size)
+		printf("*** Operation Not Supported ***\n");
+
+	for (i = 0; i < rss->key_size; i++) {
+		if (i == (rss->key_size - 1))
+			printf("%02x\n", (u8) hkey[i]);
+		else
+			printf("%02x:", (u8) hkey[i]);
+	}
 	return 0;
 }
 
-static int do_srxfhindir(struct cmd_context *ctx)
+
+
+
+static int do_srxfh(struct cmd_context *ctx)
 {
+	struct ethtool_rxfh rss_head;
+	struct ethtool_rxfh *rss;
+	struct ethtool_rxnfc ring_count;
 	int rxfhindir_equal = 0;
 	char **rxfhindir_weight = NULL;
-	struct ethtool_rxfh_indir indir_head;
-	struct ethtool_rxfh_indir *indir;
-	u32 i;
+	char *rss_hkey = NULL;
 	int err;
+	u32 i, arg_num = 0, indir_bytes = 0;
+	u32 entry_size = sizeof(rss_head.rss_config[0]);
+	u8 parse_indir = 1;
 
 	if (ctx->argc < 2)
 		exit_bad_args();
-	if (!strcmp(ctx->argp[0], "equal")) {
-		if (ctx->argc != 2)
-			exit_bad_args();
-		rxfhindir_equal = get_int_range(ctx->argp[1], 0, 1, INT_MAX);
-	} else if (!strcmp(ctx->argp[0], "weight")) {
-		rxfhindir_weight = ctx->argp + 1;
-	} else {
-		exit_bad_args();
+
+	ring_count.cmd = ETHTOOL_GRXRINGS;
+	err = send_ioctl(ctx, &ring_count);
+	if (err < 0) {
+		perror("Cannot get RX ring count");
+		return 102;
 	}
 
-	indir_head.cmd = ETHTOOL_GRXFHINDIR;
-	indir_head.size = 0;
-	err = send_ioctl(ctx, &indir_head);
+	rss_head.cmd = ETHTOOL_GRSSH;
+	rss_head.indir_size = 0;
+	rss_head.key_size = 0;
+	err = send_ioctl(ctx, &rss_head);
 	if (err < 0) {
-		perror("Cannot get RX flow hash indirection table size");
-		return 104;
+		perror("Cannot get RX flow hash indirection and key size");
+		return 103;
 	}
 
-	indir = malloc(sizeof(*indir) +
-		       indir_head.size * sizeof(*indir->ring_index));
-	indir->cmd = ETHTOOL_SRXFHINDIR;
-	indir->size = indir_head.size;
+	if (!strcmp(ctx->argp[0], "hkey")) {
+		err = parse_hkey(&rss_hkey, rss_head.key_size,
+				 ctx->argp[1]);
+		if (err < 0)
+			return err;
+
+		arg_num = 2;
+		if (!ctx->argp[arg_num])
+			parse_indir = 0;
+	}
 
+	if (parse_indir) {
+		if (!strcmp(ctx->argp[arg_num], "equal"))
+			rxfhindir_equal = get_int_range(ctx->argp[arg_num + 1],
+							0, 1, INT_MAX);
+		else if (!strcmp(ctx->argp[arg_num], "weight"))
+			rxfhindir_weight = ctx->argp + arg_num + 1;
+		else
+			exit_bad_args();
+
+		indir_bytes = rss_head.indir_size * entry_size;
+	}
+
+	rss = malloc(sizeof(*rss) + indir_bytes + rss_head.key_size);
+	rss->cmd = ETHTOOL_SRSSH;
+	rss->indir_size = rss_head.indir_size;
+	rss->key_size = rss_head.key_size;
+
+	/*
+	 * indir_size = 0 ==> reset indir to default
+	 * indir_size = 0xDEADBEEF ==> ignore indir
+	 */
 	if (rxfhindir_equal) {
-		for (i = 0; i < indir->size; i++)
-			indir->ring_index[i] = i % rxfhindir_equal;
-	} else {
+		for (i = 0; i < rss->indir_size; i++)
+			rss->rss_config[i] = i % rxfhindir_equal;
+		arg_num += 2;
+		if (ctx->argp[arg_num] &&
+		    !strcmp(ctx->argp[arg_num], "hkey")) {
+			err = parse_hkey(&rss_hkey, rss_head.key_size,
+					 ctx->argp[arg_num + 1]);
+			if (err < 0)
+				return err;
+		}
+	} else if (rxfhindir_weight) {
 		u32 j, weight, sum = 0, partial = 0;
 
 		for (j = 0; rxfhindir_weight[j]; j++) {
+			if (!strcmp(rxfhindir_weight[j], "hkey")) {
+				err = parse_hkey(&rss_hkey,
+						 rss_head.key_size,
+						 rxfhindir_weight[++j]);
+				if (err < 0)
+					return err;
+				break;
+			}
 			weight = get_u32(rxfhindir_weight[j], 0);
 			sum += weight;
 		}
@@ -3131,7 +3268,7 @@ static int do_srxfhindir(struct cmd_context *ctx)
 			exit(1);
 		}
 
-		if (sum > indir->size) {
+		if (sum > rss->indir_size) {
 			fprintf(stderr,
 				"Total weight exceeds the size of the "
 				"indirection table\n");
@@ -3139,22 +3276,31 @@ static int do_srxfhindir(struct cmd_context *ctx)
 		}
 
 		j = -1;
-		for (i = 0; i < indir->size; i++) {
-			while (i >= indir->size * partial / sum) {
+		for (i = 0; i < rss->indir_size; i++) {
+			while (i >= rss->indir_size * partial / sum) {
 				j += 1;
 				weight = get_u32(rxfhindir_weight[j], 0);
 				partial += weight;
 			}
-			indir->ring_index[i] = j;
+			rss->rss_config[i] = j;
 		}
+	} else {
+		rss->indir_size = 0xDEADBEEF;
 	}
 
-	err = send_ioctl(ctx, indir);
+	if (rss_hkey) {
+		memcpy((char *)rss->rss_config + indir_bytes,
+		       rss_hkey, rss->key_size);
+		free(rss_hkey);
+	} else {
+		rss->key_size = 0;
+	}
+
+	err = send_ioctl(ctx, rss);
 	if (err < 0) {
-		perror("Cannot set RX flow hash indirection table");
+		perror("Cannot set RX flow hash configuration");
 		return 105;
 	}
-
 	return 0;
 }
 
@@ -3833,11 +3979,12 @@ static const struct option {
 	  "		delete %d\n" },
 	{ "-T|--show-time-stamping", 1, do_tsinfo,
 	  "Show time stamping capabilities" },
-	{ "-x|--show-rxfh-indir", 1, do_grxfhindir,
-	  "Show Rx flow hash indirection" },
-	{ "-X|--set-rxfh-indir", 1, do_srxfhindir,
-	  "Set Rx flow hash indirection",
-	  "		equal N | weight W0 W1 ...\n" },
+	{ "-x|--show-rxfh-indir|--show-rxfh", 1, do_grxfh,
+	  "Show Rx flow hash indirection and/or hashkey" },
+	{ "-X|--set-rxfh-indir|--rxfh", 1, do_srxfh,
+	  "Set Rx flow hash indirection and/or hashkey",
+	  "		equal N | weight W0 W1 ...\n"
+	  "		[ hkey %x:%x:%x:%x:%x:.... ]\n" },
 	{ "-f|--flash", 1, do_flash,
 	  "Flash firmware image from the specified file to a region on the device",
 	  "               FILENAME [ REGION-NUMBER-TO-FLASH ]\n" },
-- 
1.7.1

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

end of thread, other threads:[~2014-02-28 12:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1393589444-10721-1-git-send-email-VenkatKumar.Duvvuru@Emulex.com>
2014-02-28 12:10 ` [PATCH v3 ethtool 1/2] ethtool: Support for configurable RSS hash key Venkat Duvvuru
2014-02-28 12:10 ` [PATCH v3 ethtool 2/2] " Venkat Duvvuru

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.