diff mbox

[dpdk-dev,v3,7/8] ethdev: support of multiple sizes of redirection table

Message ID 1413978810-24610-8-git-send-email-helin.zhang@intel.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Helin Zhang Oct. 22, 2014, 11:53 a.m. UTC
As 40G NIC supports different sizes (128/512/64 entries) of
redirection table from that (128 entries) of 1G and 10G NICs,
support of multiple sizes of redirection table is needed.
It includes,
* Redefine 'struct rte_eth_rss_reta' in ethdev.
  - To 'struct rte_eth_rss_reta_entry64' which contains 64
    entries and 64 bits mask.
  - Array of above new structure can be used for any number
    of redirection table entries, as long as the number is
    multiple of 64. This is quite flexible for the future
    expanding of redirection table.
* Redefinition of relevant interfaces in ethdev.
  - Interface of reta update has been redefined with new
    parameters.
  - Interface of reta query has been redefined with new
    parameters.
* Rework of 1G PMD in igb.
  - reta update has been reworked.
  - reta query has been reworked.
* Rework of 10G PMD in ixgbe.
  - reta update has been reworked.
  - reta query has been reworked.
* Rework of 40G PMD (PF only) in i40e.
  - reta update has been reworked.
  - reta query has been reworked.
* Implement relevant commands in testpmd.

Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
 app/test-pmd/cmdline.c              | 152 ++++++++++++++++++++++++++----------
 app/test-pmd/config.c               |  37 +++++----
 app/test-pmd/testpmd.h              |   4 +-
 lib/librte_ether/rte_ethdev.c       | 116 ++++++++++++++++-----------
 lib/librte_ether/rte_ethdev.h       |  38 +++++----
 lib/librte_pmd_e1000/igb_ethdev.c   | 109 +++++++++++++-------------
 lib/librte_pmd_i40e/i40e_ethdev.c   |  93 ++++++++++++----------
 lib/librte_pmd_i40e/i40e_ethdev.h   |  12 +++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 108 +++++++++++++------------
 9 files changed, 405 insertions(+), 264 deletions(-)

v2 changes:
* Put rework of updating/querying igb reta to a single patch.
* Put rework of updating/querying ixgbe reta to a single patch.
* Put rework of updating/querying i40e reta to a single patch.

v3 changes:
* Put all redefinitions of structures and interfaces into a
  single patch.
* Put all reworks of igb/igbe/i40e of supporting multiple sizes
  of reta into the same patch.
* Put all relevant testpmd reworks of supporting multiple sizes
  of reta into the same patch.

Comments

Thomas Monjalon Oct. 27, 2014, 2:23 p.m. UTC | #1
2014-10-22 19:53, Helin Zhang:
> +#define RTE_BIT_WIDTH_64 (CHAR_BIT * sizeof(uint64_t))

How can it be different of 64?
Using 64 would be simpler to understand than RTE_BIT_WIDTH_64.

> +	uint8_t reta[RTE_BIT_WIDTH_64]; /**< 64 redirection table entries. */

Even your comment is saying that it's 64.
Helin Zhang Oct. 28, 2014, 12:37 a.m. UTC | #2
Hi Thomas

See my answers inlined.

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Monday, October 27, 2014 10:24 PM
> To: Zhang, Helin
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 7/8] ethdev: support of multiple sizes of
> redirection table
> 
> 2014-10-22 19:53, Helin Zhang:
> > +#define RTE_BIT_WIDTH_64 (CHAR_BIT * sizeof(uint64_t))
> 
> How can it be different of 64?
> Using 64 would be simpler to understand than RTE_BIT_WIDTH_64.
> 
> > +	uint8_t reta[RTE_BIT_WIDTH_64]; /**< 64 redirection table entries. */
We always try to use macro in code to replace numeric, this can get the numeric more understandable.

> 
> Even your comment is saying that it's 64.
> 
> --
> Thomas

Regards,
Helin
Thomas Monjalon Oct. 28, 2014, 10:04 a.m. UTC | #3
2014-10-28 00:37, Zhang, Helin:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > 2014-10-22 19:53, Helin Zhang:
> > > +#define RTE_BIT_WIDTH_64 (CHAR_BIT * sizeof(uint64_t))
> > 
> > How can it be different of 64?
> > Using 64 would be simpler to understand than RTE_BIT_WIDTH_64.
> > 
> > > +	uint8_t reta[RTE_BIT_WIDTH_64]; /**< 64 redirection table entries. */
> We always try to use macro in code to replace numeric, this can get the numeric more understandable.

How bit width 64 is more understandable than 64?
Especially when you count a number of entries, not a bit width.
RETA_ENTRIES_MAX would be more understandable.
Helin Zhang Oct. 31, 2014, 1:39 a.m. UTC | #4
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Tuesday, October 28, 2014 6:05 PM
> To: Zhang, Helin
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 7/8] ethdev: support of multiple sizes of
> redirection table
> 
> 2014-10-28 00:37, Zhang, Helin:
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > 2014-10-22 19:53, Helin Zhang:
> > > > +#define RTE_BIT_WIDTH_64 (CHAR_BIT * sizeof(uint64_t))
> > >
> > > How can it be different of 64?
> > > Using 64 would be simpler to understand than RTE_BIT_WIDTH_64.
> > >
> > > > +	uint8_t reta[RTE_BIT_WIDTH_64]; /**< 64 redirection table entries. */
> > We always try to use macro in code to replace numeric, this can get the numeric
> more understandable.
> 
> How bit width 64 is more understandable than 64?
> Especially when you count a number of entries, not a bit width.
> RETA_ENTRIES_MAX would be more understandable.
Renaming the macro is needed. I plan to rename it to RTE_RETA_GROUP_SIZE,
as it is a group of 64 reta entries, but not the maximum number of valid entries.

> 
> --
> Thomas

Regards,
Helin
Thomas Monjalon Oct. 31, 2014, 8:46 a.m. UTC | #5
2014-10-31 01:39, Zhang, Helin:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > 2014-10-28 00:37, Zhang, Helin:
> > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > > 2014-10-22 19:53, Helin Zhang:
> > > > > +#define RTE_BIT_WIDTH_64 (CHAR_BIT * sizeof(uint64_t))
> > > >
> > > > How can it be different of 64?
> > > > Using 64 would be simpler to understand than RTE_BIT_WIDTH_64.
> > > >
> > > > > +	uint8_t reta[RTE_BIT_WIDTH_64]; /**< 64 redirection table entries. */
> > > We always try to use macro in code to replace numeric, this can get the numeric
> > more understandable.
> > 
> > How bit width 64 is more understandable than 64?
> > Especially when you count a number of entries, not a bit width.
> > RETA_ENTRIES_MAX would be more understandable.
> 
> Renaming the macro is needed. I plan to rename it to RTE_RETA_GROUP_SIZE,
> as it is a group of 64 reta entries, but not the maximum number of valid entries.

OK, good.
diff mbox

Patch

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 9de574d..8a55fb5 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -59,6 +59,7 @@ 
 #include <rte_cycles.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
@@ -186,6 +187,11 @@  static void cmd_help_long_parsed(void *parsed_result,
 			"show port (info|stats|xstats|fdir|stat_qmap) (port_id|all)\n"
 			"    Display information for port_id, or all.\n\n"
 
+			"show port X rss reta (size) (mask0,mask1,...)\n"
+			"    Display the rss redirection table entry indicated"
+			" by masks on port X. size is used to indicate the"
+			" hardware supported reta size\n\n"
+
 			"show port rss-hash [key]\n"
 			"    Display the RSS hash functions and RSS hash key"
 			" of port X\n\n"
@@ -1539,11 +1545,13 @@  struct cmd_config_rss_reta {
 };
 
 static int
-parse_reta_config(const char *str, struct rte_eth_rss_reta *reta_conf)
+parse_reta_config(const char *str,
+		  struct rte_eth_rss_reta_entry64 *reta_conf,
+		  uint16_t nb_entries)
 {
 	int i;
 	unsigned size;
-	uint8_t hash_index;
+	uint16_t hash_index, idx, shift;
 	uint8_t nb_queue;
 	char s[256];
 	const char *p, *p0 = str;
@@ -1571,24 +1579,23 @@  parse_reta_config(const char *str, struct rte_eth_rss_reta *reta_conf)
 		for (i = 0; i < _NUM_FLD; i++) {
 			errno = 0;
 			int_fld[i] = strtoul(str_fld[i], &end, 0);
-			if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+			if (errno != 0 || end == str_fld[i] ||
+					int_fld[i] > 65535)
 				return -1;
 		}
 
-		hash_index = (uint8_t)int_fld[FLD_HASH_INDEX];
+		hash_index = (uint16_t)int_fld[FLD_HASH_INDEX];
 		nb_queue = (uint8_t)int_fld[FLD_QUEUE];
 
-		if (hash_index >= ETH_RSS_RETA_NUM_ENTRIES) {
-			printf("Invalid RETA hash index=%d", hash_index);
+		if (hash_index >= nb_entries) {
+			printf("Invalid RETA hash index=%d\n", hash_index);
 			return -1;
 		}
 
-		if (hash_index < ETH_RSS_RETA_NUM_ENTRIES/2)
-			reta_conf->mask_lo |= (1ULL << hash_index);
-		else
-			reta_conf->mask_hi |= (1ULL << (hash_index - ETH_RSS_RETA_NUM_ENTRIES/2));
-
-		reta_conf->reta[hash_index] = nb_queue;
+		idx = hash_index / RTE_BIT_WIDTH_64;
+		shift = hash_index % RTE_BIT_WIDTH_64;
+		reta_conf[idx].mask |= (1ULL << shift);
+		reta_conf[idx].reta[shift] = nb_queue;
 	}
 
 	return 0;
@@ -1600,20 +1607,38 @@  cmd_set_rss_reta_parsed(void *parsed_result,
 			__attribute__((unused)) void *data)
 {
 	int ret;
-	struct rte_eth_rss_reta reta_conf;
+	struct rte_eth_dev_info dev_info;
+	struct rte_eth_rss_reta_entry64 reta_conf[8];
 	struct cmd_config_rss_reta *res = parsed_result;
 
-	memset(&reta_conf, 0, sizeof(struct rte_eth_rss_reta));
+	memset(&dev_info, 0, sizeof(dev_info));
+	rte_eth_dev_info_get(res->port_id, &dev_info);
+	if (dev_info.reta_size == 0) {
+		printf("Redirection table size is 0 which is "
+					"invalid for RSS\n");
+		return;
+	} else
+		printf("The reta size of port %d is %u\n",
+			res->port_id, dev_info.reta_size);
+	if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) {
+		printf("Currently do not support more than %u entries of "
+			"redirection table\n", ETH_RSS_RETA_SIZE_512);
+		return;
+	}
+
+	memset(reta_conf, 0, sizeof(reta_conf));
 	if (!strcmp(res->list_name, "reta")) {
-		if (parse_reta_config(res->list_of_items, &reta_conf)) {
-			printf("Invalid RSS Redirection Table config "
-							"entered\n");
+		if (parse_reta_config(res->list_of_items, reta_conf,
+						dev_info.reta_size)) {
+			printf("Invalid RSS Redirection Table "
+					"config entered\n");
 			return;
 		}
-		ret = rte_eth_dev_rss_reta_update(res->port_id, &reta_conf);
+		ret = rte_eth_dev_rss_reta_update(res->port_id,
+				reta_conf, dev_info.reta_size);
 		if (ret != 0)
 			printf("Bad redirection table parameter, "
-					"return code = %d\n", ret);
+					"return code = %d \n", ret);
 	}
 }
 
@@ -1652,26 +1677,73 @@  struct cmd_showport_reta {
 	uint8_t port_id;
 	cmdline_fixed_string_t rss;
 	cmdline_fixed_string_t reta;
-	uint64_t mask_lo;
-	uint64_t mask_hi;
+	uint16_t size;
+	cmdline_fixed_string_t list_of_items;
 };
 
-static void cmd_showport_reta_parsed(void *parsed_result,
-				__attribute__((unused)) struct cmdline *cl,
-				__attribute__((unused)) void *data)
+static int
+showport_parse_reta_config(struct rte_eth_rss_reta_entry64 *conf,
+			   uint16_t nb_entries,
+			   char *str)
 {
-	struct cmd_showport_reta *res = parsed_result;
-	struct rte_eth_rss_reta reta_conf;
+	uint32_t size;
+	const char *p, *p0 = str;
+	char s[256];
+	char *end;
+	char *str_fld[8];
+	uint16_t i, num = nb_entries / RTE_BIT_WIDTH_64;
+	int ret;
 
-	if ((res->mask_lo == 0) && (res->mask_hi == 0)) {
-		printf("Invalid RSS Redirection Table config entered\n");
-		return;
+	p = strchr(p0, '(');
+	if (p == NULL)
+		return -1;
+	p++;
+	p0 = strchr(p, ')');
+	if (p0 == NULL)
+		return -1;
+	size = p0 - p;
+	if (size >= sizeof(s)) {
+		printf("The string size exceeds the internal buffer size\n");
+		return -1;
 	}
+	snprintf(s, sizeof(s), "%.*s", size, p);
+	ret = rte_strsplit(s, sizeof(s), str_fld, num, ',');
+	if (ret <= 0 || ret != num) {
+		printf("The bits of masks do not match the number of "
+					"reta entries: %u\n", num);
+		return -1;
+	}
+	for (i = 0; i < ret; i++)
+		conf[i].mask = (uint64_t)strtoul(str_fld[i], &end, 0);
 
-	reta_conf.mask_lo = res->mask_lo;
-	reta_conf.mask_hi = res->mask_hi;
+	return 0;
+}
 
-	port_rss_reta_info(res->port_id,&reta_conf);
+static void
+cmd_showport_reta_parsed(void *parsed_result,
+			 __attribute__((unused)) struct cmdline *cl,
+			 __attribute__((unused)) void *data)
+{
+	struct cmd_showport_reta *res = parsed_result;
+	struct rte_eth_rss_reta_entry64 reta_conf[8];
+	struct rte_eth_dev_info dev_info;
+
+	memset(&dev_info, 0, sizeof(dev_info));
+	rte_eth_dev_info_get(res->port_id, &dev_info);
+	if (dev_info.reta_size == 0 || res->size != dev_info.reta_size ||
+				res->size > ETH_RSS_RETA_SIZE_512) {
+		printf("Invalid redirection table size: %u\n", res->size);
+		return;
+	}
+
+	memset(reta_conf, 0, sizeof(reta_conf));
+	if (showport_parse_reta_config(reta_conf, res->size,
+				res->list_of_items) < 0) {
+		printf("Invalid string: %s for reta masks\n",
+					res->list_of_items);
+		return;
+	}
+	port_rss_reta_info(res->port_id, reta_conf, res->size);
 }
 
 cmdline_parse_token_string_t cmd_showport_reta_show =
@@ -1684,24 +1756,24 @@  cmdline_parse_token_string_t cmd_showport_reta_rss =
 	TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, rss, "rss");
 cmdline_parse_token_string_t cmd_showport_reta_reta =
 	TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, reta, "reta");
-cmdline_parse_token_num_t cmd_showport_reta_mask_lo =
-	TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, mask_lo, UINT64);
-cmdline_parse_token_num_t cmd_showport_reta_mask_hi =
-	TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, mask_hi, UINT64);
+cmdline_parse_token_num_t cmd_showport_reta_size =
+	TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, size, UINT16);
+cmdline_parse_token_string_t cmd_showport_reta_list_of_items =
+	TOKEN_STRING_INITIALIZER(struct cmd_showport_reta,
+					list_of_items, NULL);
 
 cmdline_parse_inst_t cmd_showport_reta = {
 	.f = cmd_showport_reta_parsed,
 	.data = NULL,
-	.help_str = "show port X rss reta mask_lo mask_hi (X = port number)\n\
-			(mask_lo and mask_hi is UINT64)",
+	.help_str = "show port X rss reta (size) (mask0,mask1,...)",
 	.tokens = {
 		(void *)&cmd_showport_reta_show,
 		(void *)&cmd_showport_reta_port,
 		(void *)&cmd_showport_reta_port_id,
 		(void *)&cmd_showport_reta_rss,
 		(void *)&cmd_showport_reta_reta,
-		(void *)&cmd_showport_reta_mask_lo,
-		(void *)&cmd_showport_reta_mask_hi,
+		(void *)&cmd_showport_reta_size,
+		(void *)&cmd_showport_reta_list_of_items,
 		NULL,
 	},
 };
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 84c59b7..2287ccc 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -288,6 +288,7 @@  port_infos_display(portid_t port_id)
 	struct rte_port *port;
 	struct ether_addr mac_addr;
 	struct rte_eth_link link;
+	struct rte_eth_dev_info dev_info;
 	int vlan_offload;
 	struct rte_mempool * mp;
 	static const char *info_border = "*********************";
@@ -343,6 +344,11 @@  port_infos_display(portid_t port_id)
 		else
 			printf("  qinq(extend) off \n");
 	}
+
+	memset(&dev_info, 0, sizeof(dev_info));
+	rte_eth_dev_info_get(port_id, &dev_info);
+	if (dev_info.reta_size > 0)
+		printf("Redirection table size: %u\n", dev_info.reta_size);
 }
 
 int
@@ -762,36 +768,29 @@  rxtx_config_display(void)
 }
 
 void
-port_rss_reta_info(portid_t port_id,struct rte_eth_rss_reta *reta_conf)
+port_rss_reta_info(portid_t port_id,
+		   struct rte_eth_rss_reta_entry64 *reta_conf,
+		   uint16_t nb_entries)
 {
-	uint8_t i, j;
+	uint16_t i, idx, shift;
 	int ret;
 
 	if (port_id_is_invalid(port_id))
 		return;
 
-	ret = rte_eth_dev_rss_reta_query(port_id, reta_conf);
+	ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
 	if (ret != 0) {
 		printf("Failed to get RSS RETA info, return code = %d\n", ret);
 		return;
 	}
 
-	if (reta_conf->mask_lo != 0) {
-		for (i = 0; i< ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
-			if (reta_conf->mask_lo & (uint64_t)(1ULL << i))
-				printf("RSS RETA configuration: hash index=%d,"
-					"queue=%d\n",i,reta_conf->reta[i]);
-		}
-	}
-
-	if (reta_conf->mask_hi != 0) {
-		for (i = 0; i< ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
-			if(reta_conf->mask_hi & (uint64_t)(1ULL << i)) {
-				j = (uint8_t)(i + ETH_RSS_RETA_NUM_ENTRIES/2);
-				printf("RSS RETA configuration: hash index=%d,"
-					"queue=%d\n",j,reta_conf->reta[j]);
-			}
-		}
+	for (i = 0; i < nb_entries; i++) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		if (!(reta_conf[idx].mask & (1ULL << shift)))
+			continue;
+		printf("RSS RETA configuration: hash index=%u, queue=%u\n",
+					i, reta_conf[idx].reta[shift]);
 	}
 }
 
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9cbfeac..10bf13f 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -533,7 +533,9 @@  void fdir_remove_perfect_filter(portid_t port_id, uint16_t soft_id,
 				struct rte_fdir_filter *fdir_filter);
 void fdir_set_masks(portid_t port_id, struct rte_fdir_masks *fdir_masks);
 
-void port_rss_reta_info(portid_t port_id, struct rte_eth_rss_reta *reta_conf);
+void port_rss_reta_info(portid_t port_id,
+			struct rte_eth_rss_reta_entry64 *reta_conf,
+			uint16_t nb_entries);
 
 void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
 void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id,
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 50f10d9..0b72057 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1926,78 +1926,104 @@  rte_eth_dev_priority_flow_ctrl_set(uint8_t port_id, struct rte_eth_pfc_conf *pfc
 	return (-ENOTSUP);
 }
 
-int
-rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
+static inline int
+rte_eth_check_reta_mask(struct rte_eth_rss_reta_entry64 *reta_conf,
+			uint16_t reta_size)
 {
-	struct rte_eth_dev *dev;
-	uint16_t max_rxq;
-	uint8_t i,j;
+	uint16_t i, num = reta_size / RTE_BIT_WIDTH_64;
 
-	if (port_id >= nb_ports) {
-		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
-		return (-ENODEV);
-	}
+	if (!reta_conf)
+		return -EINVAL;
 
-	/* Invalid mask bit(s) setting */
-	if ((reta_conf->mask_lo == 0) && (reta_conf->mask_hi == 0)) {
-		PMD_DEBUG_TRACE("Invalid update mask bits for port=%d\n",port_id);
-		return (-EINVAL);
+	for (i = 0; i < num; i++) {
+		if (reta_conf[i].mask)
+			return 0;
 	}
 
-	dev = &rte_eth_devices[port_id];
-	max_rxq = (dev->data->nb_rx_queues <= ETH_RSS_RETA_MAX_QUEUE) ?
-		dev->data->nb_rx_queues : ETH_RSS_RETA_MAX_QUEUE;
-	if (reta_conf->mask_lo != 0) {
-		for (i = 0; i < ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
-			if ((reta_conf->mask_lo & (1ULL << i)) &&
-				(reta_conf->reta[i] >= max_rxq)) {
-				PMD_DEBUG_TRACE("RETA hash index output"
-					"configration for port=%d,invalid"
-					"queue=%d\n",port_id,reta_conf->reta[i]);
+	return -EINVAL;
+}
 
-				return (-EINVAL);
-			}
+static inline int
+rte_eth_check_reta_entry(struct rte_eth_rss_reta_entry64 *reta_conf,
+			 uint16_t reta_size,
+			 uint8_t max_rxq)
+{
+	uint16_t i, idx, shift;
+
+	if (!reta_conf)
+		return -EINVAL;
+
+	if (max_rxq == 0) {
+		PMD_DEBUG_TRACE("No receive queue is available\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < reta_size; i++) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		if ((reta_conf[idx].mask & (0x1 << shift)) &&
+			(reta_conf[idx].reta[shift] >= max_rxq)) {
+			PMD_DEBUG_TRACE("reta_conf[%u]->reta[%u]: %u exceeds "
+				"the maximum rxq index: %u\n", idx, shift,
+				reta_conf[idx].reta[shift], max_rxq);
+			return -EINVAL;
 		}
 	}
 
-	if (reta_conf->mask_hi != 0) {
-		for (i = 0; i< ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
-			j = (uint8_t)(i + ETH_RSS_RETA_NUM_ENTRIES/2);
+	return 0;
+}
 
-			/* Check if the max entry >= 128 */
-			if ((reta_conf->mask_hi & (1ULL << i)) &&
-				(reta_conf->reta[j] >= max_rxq)) {
-				PMD_DEBUG_TRACE("RETA hash index output"
-					"configration for port=%d,invalid"
-					"queue=%d\n",port_id,reta_conf->reta[j]);
+int
+rte_eth_dev_rss_reta_update(uint8_t port_id,
+			    struct rte_eth_rss_reta_entry64 *reta_conf,
+			    uint16_t reta_size)
+{
+	struct rte_eth_dev *dev;
+	int ret;
 
-				return (-EINVAL);
-			}
-		}
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return -ENODEV;
 	}
 
+	/* Check mask bits */
+	ret = rte_eth_check_reta_mask(reta_conf, reta_size);
+	if (ret < 0)
+		return ret;
+
+	dev = &rte_eth_devices[port_id];
+
+	/* Check entry value */
+	ret = rte_eth_check_reta_entry(reta_conf, reta_size,
+				dev->data->nb_rx_queues);
+	if (ret < 0)
+		return ret;
+
 	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_update, -ENOTSUP);
-	return (*dev->dev_ops->reta_update)(dev, reta_conf);
+	return (*dev->dev_ops->reta_update)(dev, reta_conf, reta_size);
 }
 
 int
-rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
+rte_eth_dev_rss_reta_query(uint8_t port_id,
+			   struct rte_eth_rss_reta_entry64 *reta_conf,
+			   uint16_t reta_size)
 {
 	struct rte_eth_dev *dev;
+	int ret;
 
 	if (port_id >= nb_ports) {
 		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
-		return (-ENODEV);
+		return -ENODEV;
 	}
 
-	if((reta_conf->mask_lo == 0) && (reta_conf->mask_hi == 0)) {
-		PMD_DEBUG_TRACE("Invalid update mask bits for the port=%d\n",port_id);
-		return (-EINVAL);
-	}
+	/* Check mask bits */
+	ret = rte_eth_check_reta_mask(reta_conf, reta_size);
+	if (ret < 0)
+		return ret;
 
 	dev = &rte_eth_devices[port_id];
 	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_query, -ENOTSUP);
-	return (*dev->dev_ops->reta_query)(dev, reta_conf);
+	return (*dev->dev_ops->reta_query)(dev, reta_conf, reta_size);
 }
 
 int
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index ed2f15a..a8b93e5 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -428,12 +428,12 @@  struct rte_eth_rss_conf {
 		ETH_RSS_L2_PAYLOAD)
 
 /* Definitions used for redirection table entry size */
-#define ETH_RSS_RETA_NUM_ENTRIES 128
-#define ETH_RSS_RETA_MAX_QUEUE   16
 #define ETH_RSS_RETA_SIZE_64  64
 #define ETH_RSS_RETA_SIZE_128 128
 #define ETH_RSS_RETA_SIZE_512 512
 
+#define RTE_BIT_WIDTH_64 (CHAR_BIT * sizeof(uint64_t))
+
 /* Definitions used for VMDQ and DCB functionality */
 #define ETH_VMDQ_MAX_VLAN_FILTERS   64 /**< Maximum nb. of VMDQ vlan filters. */
 #define ETH_DCB_NUM_USER_PRIORITIES 8  /**< Maximum nb. of DCB priorities. */
@@ -496,15 +496,15 @@  struct rte_eth_vmdq_mirror_conf {
 };
 
 /**
- * A structure used to configure Redirection Table of  the Receive Side
- * Scaling (RSS) feature of an Ethernet port.
+ * A structure used to configure 64 entries of Redirection Table of the
+ * Receive Side Scaling (RSS) feature of an Ethernet port. To configure
+ * more than 64 entries supported by hardware, an array of this structure
+ * is needed.
  */
-struct rte_eth_rss_reta {
-	/** First 64 mask bits indicate which entry(s) need to updated/queried. */
-	uint64_t mask_lo;
-	/** Second 64 mask bits indicate which entry(s) need to updated/queried. */
-	uint64_t mask_hi;
-	uint8_t reta[ETH_RSS_RETA_NUM_ENTRIES];  /**< 128 RETA entries*/
+struct rte_eth_rss_reta_entry64 {
+	uint64_t mask;
+	/**< Mask bits indicate which entries need to be updated/queried. */
+	uint8_t reta[RTE_BIT_WIDTH_64]; /**< 64 redirection table entries. */
 };
 
 /**
@@ -1189,11 +1189,13 @@  typedef int (*priority_flow_ctrl_set_t)(struct rte_eth_dev *dev,
 /**< @internal Setup priority flow control parameter on an Ethernet device */
 
 typedef int (*reta_update_t)(struct rte_eth_dev *dev,
-				struct rte_eth_rss_reta *reta_conf);
+			     struct rte_eth_rss_reta_entry64 *reta_conf,
+			     uint16_t reta_size);
 /**< @internal Update RSS redirection table on an Ethernet device */
 
 typedef int (*reta_query_t)(struct rte_eth_dev *dev,
-				struct rte_eth_rss_reta *reta_conf);
+			    struct rte_eth_rss_reta_entry64 *reta_conf,
+			    uint16_t reta_size);
 /**< @internal Query RSS redirection table on an Ethernet device */
 
 typedef int (*rss_hash_update_t)(struct rte_eth_dev *dev,
@@ -2918,14 +2920,17 @@  int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr);
  * @param port
  *   The port identifier of the Ethernet device.
  * @param reta_conf
- *    RETA to update.
+ *   RETA to update.
+ * @param reta_size
+ *   Redirection table size.
  * @return
  *   - (0) if successful.
  *   - (-ENOTSUP) if hardware doesn't support.
  *   - (-EINVAL) if bad parameter.
  */
 int rte_eth_dev_rss_reta_update(uint8_t port,
-			struct rte_eth_rss_reta *reta_conf);
+				struct rte_eth_rss_reta_entry64 *reta_conf,
+				uint16_t reta_size);
 
  /**
  * Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device.
@@ -2934,13 +2939,16 @@  int rte_eth_dev_rss_reta_update(uint8_t port,
  *   The port identifier of the Ethernet device.
  * @param reta_conf
  *   RETA to query.
+ * @param reta_size
+ *   Redirection table size.
  * @return
  *   - (0) if successful.
  *   - (-ENOTSUP) if hardware doesn't support.
  *   - (-EINVAL) if bad parameter.
  */
 int rte_eth_dev_rss_reta_query(uint8_t port,
-			struct rte_eth_rss_reta *reta_conf);
+			       struct rte_eth_rss_reta_entry64 *reta_conf,
+			       uint16_t reta_size);
 
  /**
  * Updates unicast hash table for receiving packet with the given destination
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 79998cf..a9f0f41 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -138,10 +138,11 @@  static int igbvf_vlan_filter_set(struct rte_eth_dev *dev,
 static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on);
 static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on);
 static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
-		 struct rte_eth_rss_reta *reta_conf);
+				   struct rte_eth_rss_reta_entry64 *reta_conf,
+				   uint16_t reta_size);
 static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
-		struct rte_eth_rss_reta *reta_conf);
-
+				  struct rte_eth_rss_reta_entry64 *reta_conf,
+				  uint16_t reta_size);
 static int eth_igb_add_syn_filter(struct rte_eth_dev *dev,
 			struct rte_syn_filter *filter, uint16_t rx_queue);
 static int eth_igb_remove_syn_filter(struct rte_eth_dev *dev);
@@ -2300,38 +2301,39 @@  igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 
 static int
 eth_igb_rss_reta_update(struct rte_eth_dev *dev,
-                                struct rte_eth_rss_reta *reta_conf)
+			struct rte_eth_rss_reta_entry64 *reta_conf,
+			uint16_t reta_size)
 {
-	uint8_t i,j,mask;
-	uint32_t reta;
-	struct e1000_hw *hw =
-			E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint8_t i, j, mask;
+	uint32_t reta, r;
+	uint16_t idx, shift;
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-	/*
-	 * Update Redirection Table RETA[n],n=0...31,The redirection table has
-	 * 128-entries in 32 registers
-	 */
-	for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-		if (i < ETH_RSS_RETA_NUM_ENTRIES/2)
-			mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
+	if (reta_size != ETH_RSS_RETA_SIZE_128) {
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%d) doesn't match the number hardware can supported "
+			"(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < reta_size; i += 4) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xf);
+		if (!mask)
+			continue;
+		if (mask == 0xf)
+			r = 0;
 		else
-			mask = (uint8_t)((reta_conf->mask_hi >>
-				(i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF);
-		if (mask != 0) {
-			reta = 0;
-			/* If all 4 entries were set,don't need read RETA register */
-			if (mask != 0xF)
-				reta = E1000_READ_REG(hw,E1000_RETA(i >> 2));
-
-			for (j = 0; j < 4; j++) {
-				if (mask & (0x1 << j)) {
-					if (mask != 0xF)
-						reta &= ~(0xFF << 8 * j);
-					reta |= reta_conf->reta[i + j] << 8 * j;
-				}
-			}
-			E1000_WRITE_REG(hw, E1000_RETA(i >> 2),reta);
+			r = E1000_READ_REG(hw, E1000_RETA(i >> 2));
+		for (j = 0, reta = 0; j < 4; j++) {
+			if (mask & (0x1 << j))
+				reta |= reta_conf[idx].reta[shift + j] <<
+							(CHAR_BIT * j);
+			else
+				reta |= r & (0xff << (CHAR_BIT * j));
 		}
+		E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta);
 	}
 
 	return 0;
@@ -2339,31 +2341,32 @@  eth_igb_rss_reta_update(struct rte_eth_dev *dev,
 
 static int
 eth_igb_rss_reta_query(struct rte_eth_dev *dev,
-                                struct rte_eth_rss_reta *reta_conf)
+		       struct rte_eth_rss_reta_entry64 *reta_conf,
+		       uint16_t reta_size)
 {
-	uint8_t i,j,mask;
+	uint8_t i, j, mask;
 	uint32_t reta;
-	struct e1000_hw *hw =
-			E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t idx, shift;
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-	/*
-	 * Read Redirection Table RETA[n],n=0...31,The redirection table has
-	 * 128-entries in 32 registers
-	 */
-	for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-		if (i < ETH_RSS_RETA_NUM_ENTRIES/2)
-			mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
-		else
-			mask = (uint8_t)((reta_conf->mask_hi >>
-				(i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF);
-
-		if (mask != 0) {
-			reta = E1000_READ_REG(hw,E1000_RETA(i >> 2));
-			for (j = 0; j < 4; j++) {
-				if (mask & (0x1 << j))
-					reta_conf->reta[i + j] =
-						(uint8_t)((reta >> 8 * j) & 0xFF);
-			}
+	if (reta_size != ETH_RSS_RETA_SIZE_128) {
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%d) doesn't match the number hardware can supported "
+			"(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < reta_size; i += 4) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xf);
+		if (!mask)
+			continue;
+		reta = E1000_READ_REG(hw, E1000_RETA(i >> 2));
+		for (j = 0; j < 4; j++) {
+			if (mask & (0x1 << j))
+				reta_conf[idx].reta[shift + j] =
+					((reta >> (CHAR_BIT * j)) & 0xff);
 		}
 	}
 
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index d80004c..01ead84 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -72,14 +72,6 @@ 
 /* Maximun number of VSI */
 #define I40E_MAX_NUM_VSIS          (384UL)
 
-/* Bit shift and mask */
-#define I40E_16_BIT_SHIFT 16
-#define I40E_16_BIT_MASK  0xFFFF
-#define I40E_32_BIT_SHIFT 32
-#define I40E_32_BIT_MASK  0xFFFFFFFF
-#define I40E_48_BIT_SHIFT 48
-#define I40E_48_BIT_MASK  0xFFFFFFFFFFFFULL
-
 /* Default queue interrupt throttling time in microseconds*/
 #define I40E_ITR_INDEX_DEFAULT          0
 #define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
@@ -130,9 +122,11 @@  static void i40e_macaddr_add(struct rte_eth_dev *dev,
 			  uint32_t pool);
 static void i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index);
 static int i40e_dev_rss_reta_update(struct rte_eth_dev *dev,
-				    struct rte_eth_rss_reta *reta_conf);
+				    struct rte_eth_rss_reta_entry64 *reta_conf,
+				    uint16_t reta_size);
 static int i40e_dev_rss_reta_query(struct rte_eth_dev *dev,
-				   struct rte_eth_rss_reta *reta_conf);
+				   struct rte_eth_rss_reta_entry64 *reta_conf,
+				   uint16_t reta_size);
 
 static int i40e_get_cap(struct i40e_hw *hw);
 static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
@@ -1594,32 +1588,41 @@  i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index)
 
 static int
 i40e_dev_rss_reta_update(struct rte_eth_dev *dev,
-			 struct rte_eth_rss_reta *reta_conf)
+			 struct rte_eth_rss_reta_entry64 *reta_conf,
+			 uint16_t reta_size)
 {
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t lut, l;
-	uint8_t i, j, mask, max = ETH_RSS_RETA_NUM_ENTRIES / 2;
-
-	for (i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-		if (i < max)
-			mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
-		else
-			mask = (uint8_t)((reta_conf->mask_hi >>
-						(i - max)) & 0xF);
+	uint16_t i, j, lut_size = pf->hash_lut_size;
+	uint16_t idx, shift;
+	uint8_t mask;
+
+	if (reta_size != lut_size ||
+		reta_size > ETH_RSS_RETA_SIZE_512) {
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%d) doesn't match the number hardware can supported "
+					"(%d)\n", reta_size, lut_size);
+		return -EINVAL;
+	}
 
+	for (i = 0; i < reta_size; i += I40E_4_BIT_WIDTH) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		mask = (uint8_t)((reta_conf[idx].mask >> shift) &
+						I40E_4_BIT_MASK);
 		if (!mask)
 			continue;
-
-		if (mask == 0xF)
+		if (mask == I40E_4_BIT_MASK)
 			l = 0;
 		else
 			l = I40E_READ_REG(hw, I40E_PFQF_HLUT(i >> 2));
-
-		for (j = 0, lut = 0; j < 4; j++) {
+		for (j = 0, lut = 0; j < I40E_4_BIT_WIDTH; j++) {
 			if (mask & (0x1 << j))
-				lut |= reta_conf->reta[i + j] << (8 * j);
+				lut |= reta_conf[idx].reta[shift + j] <<
+							(CHAR_BIT * j);
 			else
-				lut |= l & (0xFF << (8 * j));
+				lut |= l & (I40E_8_BIT_MASK << (CHAR_BIT * j));
 		}
 		I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut);
 	}
@@ -1629,27 +1632,37 @@  i40e_dev_rss_reta_update(struct rte_eth_dev *dev,
 
 static int
 i40e_dev_rss_reta_query(struct rte_eth_dev *dev,
-			struct rte_eth_rss_reta *reta_conf)
+			struct rte_eth_rss_reta_entry64 *reta_conf,
+			uint16_t reta_size)
 {
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t lut;
-	uint8_t i, j, mask, max = ETH_RSS_RETA_NUM_ENTRIES / 2;
-
-	for (i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-		if (i < max)
-			mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
-		else
-			mask = (uint8_t)((reta_conf->mask_hi >>
-						(i - max)) & 0xF);
+	uint16_t i, j, lut_size = pf->hash_lut_size;
+	uint16_t idx, shift;
+	uint8_t mask;
+
+	if (reta_size != lut_size ||
+		reta_size > ETH_RSS_RETA_SIZE_512) {
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%d) doesn't match the number hardware can supported "
+					"(%d)\n", reta_size, lut_size);
+		return -EINVAL;
+	}
 
+	for (i = 0; i < reta_size; i += I40E_4_BIT_WIDTH) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		mask = (uint8_t)((reta_conf[idx].mask >> shift) &
+						I40E_4_BIT_MASK);
 		if (!mask)
 			continue;
 
 		lut = I40E_READ_REG(hw, I40E_PFQF_HLUT(i >> 2));
-		for (j = 0; j < 4; j++) {
+		for (j = 0; j < I40E_4_BIT_WIDTH; j++) {
 			if (mask & (0x1 << j))
-				reta_conf->reta[i + j] =
-					(uint8_t)((lut >> (8 * j)) & 0xFF);
+				reta_conf[idx].reta[shift] = ((lut >>
+					(CHAR_BIT * j)) & I40E_8_BIT_MASK);
 		}
 	}
 
@@ -3229,7 +3242,7 @@  i40e_stat_update_32(struct i40e_hw *hw,
 		*stat = (uint64_t)(new_data - *offset);
 	else
 		*stat = (uint64_t)((new_data +
-			((uint64_t)1 << I40E_32_BIT_SHIFT)) - *offset);
+			((uint64_t)1 << I40E_32_BIT_WIDTH)) - *offset);
 }
 
 static void
@@ -3244,7 +3257,7 @@  i40e_stat_update_48(struct i40e_hw *hw,
 
 	new_data = (uint64_t)I40E_READ_REG(hw, loreg);
 	new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) &
-			I40E_16_BIT_MASK)) << I40E_32_BIT_SHIFT;
+			I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH;
 
 	if (!offset_loaded)
 		*offset = new_data;
@@ -3253,7 +3266,7 @@  i40e_stat_update_48(struct i40e_hw *hw,
 		*stat = new_data - *offset;
 	else
 		*stat = (uint64_t)((new_data +
-			((uint64_t)1 << I40E_48_BIT_SHIFT)) - *offset);
+			((uint64_t)1 << I40E_48_BIT_WIDTH)) - *offset);
 
 	*stat &= I40E_48_BIT_MASK;
 }
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h
index 0b2f316..c54cd80 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.h
+++ b/lib/librte_pmd_i40e/i40e_ethdev.h
@@ -63,6 +63,18 @@ 
 #define I40E_DEFAULT_TX_WTHRESH      0
 #define I40E_DEFAULT_TX_RSBIT_THRESH 32
 
+/* Bit shift and mask */
+#define I40E_4_BIT_WIDTH  (CHAR_BIT / 2)
+#define I40E_4_BIT_MASK   ((1 << I40E_4_BIT_WIDTH) - 1)
+#define I40E_8_BIT_WIDTH  CHAR_BIT
+#define I40E_8_BIT_MASK   ((1 << I40E_8_BIT_WIDTH) - 1)
+#define I40E_16_BIT_WIDTH (CHAR_BIT * 2)
+#define I40E_16_BIT_MASK  ((1 << I40E_16_BIT_WIDTH) - 1)
+#define I40E_32_BIT_WIDTH (CHAR_BIT * 4)
+#define I40E_32_BIT_MASK  ((1 << I40E_32_BIT_WIDTH) - 1)
+#define I40E_48_BIT_WIDTH (CHAR_BIT * 6)
+#define I40E_48_BIT_MASK  ((1ULL << I40E_48_BIT_WIDTH) - 1)
+
 /* i40e flags */
 #define I40E_FLAG_RSS                   (1ULL << 0)
 #define I40E_FLAG_DCB                   (1ULL << 1)
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index da140c8..215600e 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -159,9 +159,11 @@  static int ixgbe_flow_ctrl_set(struct rte_eth_dev *dev,
 static int ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev,
 		struct rte_eth_pfc_conf *pfc_conf);
 static int ixgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
-		struct rte_eth_rss_reta *reta_conf);
+			struct rte_eth_rss_reta_entry64 *reta_conf,
+			uint16_t reta_size);
 static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
-		struct rte_eth_rss_reta *reta_conf);
+			struct rte_eth_rss_reta_entry64 *reta_conf,
+			uint16_t reta_size);
 static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev);
 static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
@@ -2711,38 +2713,40 @@  ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *p
 
 static int
 ixgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
-				struct rte_eth_rss_reta *reta_conf)
+			  struct rte_eth_rss_reta_entry64 *reta_conf,
+			  uint16_t reta_size)
 {
-	uint8_t i,j,mask;
-	uint32_t reta;
-	struct ixgbe_hw *hw =
-			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint8_t i, j, mask;
+	uint32_t reta, r;
+	uint16_t idx, shift;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	PMD_INIT_FUNC_TRACE();
-	/*
-	* Update Redirection Table RETA[n],n=0...31,The redirection table has
-	* 128-entries in 32 registers
-	 */
-	for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-		if (i < ETH_RSS_RETA_NUM_ENTRIES/2)
-			mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
+	if (reta_size != ETH_RSS_RETA_SIZE_128) {
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%d) doesn't match the number hardware can supported "
+			"(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < reta_size; i += 4) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xf);
+		if (!mask)
+			continue;
+		if (mask == 0xf)
+			r = 0;
 		else
-			mask = (uint8_t)((reta_conf->mask_hi >>
-				(i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF);
-		if (mask != 0) {
-			reta = 0;
-			if (mask != 0xF)
-				reta = IXGBE_READ_REG(hw,IXGBE_RETA(i >> 2));
-
-			for (j = 0; j < 4; j++) {
-				if (mask & (0x1 << j)) {
-					if (mask != 0xF)
-						reta &= ~(0xFF << 8 * j);
-					reta |= reta_conf->reta[i + j] << 8*j;
-				}
-			}
-			IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2),reta);
+			r = IXGBE_READ_REG(hw, IXGBE_RETA(i >> 2));
+		for (j = 0, reta = 0; j < 4; j++) {
+			if (mask & (0x1 << j))
+				reta |= reta_conf[idx].reta[shift + j] <<
+							(CHAR_BIT * j);
+			else
+				reta |= r & (0xff << (CHAR_BIT * j));
 		}
+		IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
 	}
 
 	return 0;
@@ -2750,32 +2754,34 @@  ixgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
 
 static int
 ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
-				struct rte_eth_rss_reta *reta_conf)
+			 struct rte_eth_rss_reta_entry64 *reta_conf,
+			 uint16_t reta_size)
 {
-	uint8_t i,j,mask;
+	uint8_t i, j, mask;
 	uint32_t reta;
-	struct ixgbe_hw *hw =
-			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t idx, shift;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	PMD_INIT_FUNC_TRACE();
-	/*
-	 * Read Redirection Table RETA[n],n=0...31,The redirection table has
-	 * 128-entries in 32 registers
-	 */
-	for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) {
-		if (i < ETH_RSS_RETA_NUM_ENTRIES/2)
-			mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF);
-		else
-			mask = (uint8_t)((reta_conf->mask_hi >>
-				(i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF);
-
-		if (mask != 0) {
-			reta = IXGBE_READ_REG(hw,IXGBE_RETA(i >> 2));
-			for (j = 0; j < 4; j++) {
-				if (mask & (0x1 << j))
-					reta_conf->reta[i + j] =
-						(uint8_t)((reta >> 8 * j) & 0xFF);
-			}
+	if (reta_size != ETH_RSS_RETA_SIZE_128) {
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%d) doesn't match the number hardware can supported "
+				"(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ETH_RSS_RETA_SIZE_128; i += 4) {
+		idx = i / RTE_BIT_WIDTH_64;
+		shift = i % RTE_BIT_WIDTH_64;
+		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xf);
+		if (!mask)
+			continue;
+
+		reta = IXGBE_READ_REG(hw, IXGBE_RETA(i >> 2));
+		for (j = 0; j < 4; j++) {
+			if (mask & (0x1 << j))
+				reta_conf[idx].reta[shift + j] =
+					((reta >> (CHAR_BIT * j)) & 0xff);
 		}
 	}