diff mbox

[net-next,03/16] i40evf: Support RSS option in ethtool

Message ID 1395060316-16897-4-git-send-email-jeffrey.t.kirsher@intel.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Kirsher, Jeffrey T March 17, 2014, 12:45 p.m. UTC
From: Mitch Williams <mitch.a.williams@intel.com>

Add support for viewing and modifying RSS hash options and RSS hash
look-up table programming through ethtool. Because the lookup table is
so small for the VFs (only 16 registers), we don't bother to maintain a
shadow table in memory, we just read and write the registers directly.

Change-ID: Ib5a6924da78c540789f21d26b5e8086d71c29384
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Catherine Sullivan <catherine.sullivan@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 315 +++++++++++++++++++++
 1 file changed, 315 insertions(+)

Comments

Or Gerlitz March 17, 2014, 2:40 p.m. UTC | #1
On Mon, Mar 17, 2014 at 2:45 PM, Jeff Kirsher
<jeffrey.t.kirsher@intel.com> wrote:
> From: Mitch Williams <mitch.a.williams@intel.com>
>
> Add support for viewing and modifying RSS hash options and RSS hash
> look-up table programming through ethtool.
[...]

FWIW, this commit does more... wouldn't it be worth dropping some
words on that on that change-log?

[...]
>  static struct ethtool_ops i40evf_ethtool_ops = {
>         .get_settings           = i40evf_get_settings,
>         .get_drvinfo            = i40evf_get_drvinfo,
> @@ -378,6 +687,12 @@ static struct ethtool_ops i40evf_ethtool_ops = {
>         .set_msglevel           = i40evf_set_msglevel,
>         .get_coalesce           = i40evf_get_coalesce,
>         .set_coalesce           = i40evf_set_coalesce,
> +       .get_rxnfc              = i40evf_get_rxnfc,
> +       .set_rxnfc              = i40evf_set_rxnfc,
> +       .get_rxfh_indir_size    = i40evf_get_rxfh_indir_size,
> +       .get_rxfh_indir         = i40evf_get_rxfh_indir,
> +       .set_rxfh_indir         = i40evf_set_rxfh_indir,
> +       .get_channels           = i40evf_get_channels,
>  };
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ben Hutchings March 17, 2014, 6:53 p.m. UTC | #2
On Mon, 2014-03-17 at 05:45 -0700, Jeff Kirsher wrote:
> From: Mitch Williams <mitch.a.williams@intel.com>
> 
> Add support for viewing and modifying RSS hash options and RSS hash
> look-up table programming through ethtool. Because the lookup table is
> so small for the VFs (only 16 registers), we don't bother to maintain a
> shadow table in memory, we just read and write the registers directly.
[...]
> +static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
> +				    struct ethtool_rxnfc *cmd)
> +{
> +	cmd->data = 0;
> +
> +	/* Report default options for RSS on i40e */

But you're allowing them to be changed from the defaults, so this is
wrong.

[...]
> +static int i40evf_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
> +{
> +	struct i40evf_adapter *adapter = netdev_priv(netdev);
> +	struct i40e_hw *hw = &adapter->hw;
> +	u32 hlut_val;
> +	int i, j;
> +
> +	/* Verify user input. */
> +	for (i = 0; i < (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4; i++) {
> +		if (indir[i] >= adapter->vsi_res->num_queue_pairs)
> +			return -EINVAL;
> +	}
[...]

ethtool_set_rxfh_indir() does this validation so you don't have to.
(This wasn't true originally so you'll need to keep it in compatibility
code for your OOT driver.)

Ben.
Mitch Williams March 17, 2014, 6:55 p.m. UTC | #3
> -----Original Message-----
> From: Or Gerlitz [mailto:or.gerlitz@gmail.com]
> Sent: Monday, March 17, 2014 7:40 AM
> To: Kirsher, Jeffrey T
> Cc: David Miller; Williams, Mitch A; netdev@vger.kernel.org;
> gospo@redhat.com; sassmann@redhat.com; Sullivan, Catherine
> Subject: Re: [net-next 03/16] i40evf: Support RSS option in ethtool
> 
> On Mon, Mar 17, 2014 at 2:45 PM, Jeff Kirsher
> <jeffrey.t.kirsher@intel.com> wrote:
> > From: Mitch Williams <mitch.a.williams@intel.com>
> >
> > Add support for viewing and modifying RSS hash options and RSS hash
> > look-up table programming through ethtool.
> [...]
> 
> FWIW, this commit does more... wouldn't it be worth dropping some
> words on that on that change-log?
> 

Well, Or, I'm not sure really what to say. I added code to change which hashing options RSS would use, and code to change the RSS lookup table.

Looks like Ben has some comments, so we'll have to respin this anyway. I'm happy to change the description, just wondering what you'd like to see here.

-Mitch

> [...]
> >  static struct ethtool_ops i40evf_ethtool_ops = {
> >         .get_settings           = i40evf_get_settings,
> >         .get_drvinfo            = i40evf_get_drvinfo,
> > @@ -378,6 +687,12 @@ static struct ethtool_ops i40evf_ethtool_ops = {
> >         .set_msglevel           = i40evf_set_msglevel,
> >         .get_coalesce           = i40evf_get_coalesce,
> >         .set_coalesce           = i40evf_set_coalesce,
> > +       .get_rxnfc              = i40evf_get_rxnfc,
> > +       .set_rxnfc              = i40evf_set_rxnfc,
> > +       .get_rxfh_indir_size    = i40evf_get_rxfh_indir_size,
> > +       .get_rxfh_indir         = i40evf_get_rxfh_indir,
> > +       .set_rxfh_indir         = i40evf_set_rxfh_indir,
> > +       .get_channels           = i40evf_get_channels,
> >  };
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mitch Williams March 17, 2014, 6:55 p.m. UTC | #4
> -----Original Message-----

> From: Ben Hutchings [mailto:ben@decadent.org.uk]

> Sent: Monday, March 17, 2014 11:54 AM

> To: Kirsher, Jeffrey T

> Cc: davem@davemloft.net; Williams, Mitch A; netdev@vger.kernel.org;

> gospo@redhat.com; sassmann@redhat.com; Sullivan, Catherine

> Subject: Re: [net-next 03/16] i40evf: Support RSS option in ethtool

> 

> On Mon, 2014-03-17 at 05:45 -0700, Jeff Kirsher wrote:

> > From: Mitch Williams <mitch.a.williams@intel.com>

> >

> > Add support for viewing and modifying RSS hash options and RSS hash

> > look-up table programming through ethtool. Because the lookup table is

> > so small for the VFs (only 16 registers), we don't bother to maintain a

> > shadow table in memory, we just read and write the registers directly.

> [...]

> > +static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,

> > +				    struct ethtool_rxnfc *cmd)

> > +{

> > +	cmd->data = 0;

> > +

> > +	/* Report default options for RSS on i40e */

> 

> But you're allowing them to be changed from the defaults, so this is

> wrong.

> 

> [...]

> > +static int i40evf_set_rxfh_indir(struct net_device *netdev, const u32

> *indir)

> > +{

> > +	struct i40evf_adapter *adapter = netdev_priv(netdev);

> > +	struct i40e_hw *hw = &adapter->hw;

> > +	u32 hlut_val;

> > +	int i, j;

> > +

> > +	/* Verify user input. */

> > +	for (i = 0; i < (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4; i++) {

> > +		if (indir[i] >= adapter->vsi_res->num_queue_pairs)

> > +			return -EINVAL;

> > +	}

> [...]

> 

> ethtool_set_rxfh_indir() does this validation so you don't have to.

> (This wasn't true originally so you'll need to keep it in compatibility

> code for your OOT driver.)


Thanks, Ben. We'll respin this.

-Mitch

> 

> Ben.

> 

> --

> Ben Hutchings

> I'm always amazed by the number of people who take up solipsism because

> they heard someone else explain it. - E*Borg on alt.fan.pratchett
Or Gerlitz March 17, 2014, 9:19 p.m. UTC | #5
On Mon, Mar 17, 2014 at 8:55 PM, Williams, Mitch A
<mitch.a.williams@intel.com> wrote:
>> On Mon, Mar 17, 2014 at 2:45 PM, Jeff Kirsher
>> <jeffrey.t.kirsher@intel.com> wrote:
>> > From: Mitch Williams <mitch.a.williams@intel.com>
>> >
>> > Add support for viewing and modifying RSS hash options and RSS hash
>> > look-up table programming through ethtool.
>> [...]
>>
>> FWIW, this commit does more... wouldn't it be worth dropping some
>> words on that on that change-log?
>>
>
> Well, Or, I'm not sure really what to say. I added code to change which hashing options RSS would use, and code to change the RSS lookup table.
>
> Looks like Ben has some comments, so we'll have to respin this anyway. I'm happy to change the description, just wondering what you'd like to see here.

When I made the comment I saw that you added bunch of ethtool calls
and wasn't sure this is covered in the change log, in 2nd look I see
one entry which isn't mentioned and isn't directly related to RSS, the
one that gets the number of channels, but it's minor and I assume can
stay here, maybe even non mentioned in the change log, but that will
be according to your taste


>
> -Mitch
>
>> [...]
>> >  static struct ethtool_ops i40evf_ethtool_ops = {
>> >         .get_settings           = i40evf_get_settings,
>> >         .get_drvinfo            = i40evf_get_drvinfo,
>> > @@ -378,6 +687,12 @@ static struct ethtool_ops i40evf_ethtool_ops = {
>> >         .set_msglevel           = i40evf_set_msglevel,
>> >         .get_coalesce           = i40evf_get_coalesce,
>> >         .set_coalesce           = i40evf_set_coalesce,
>> > +       .get_rxnfc              = i40evf_get_rxnfc,
>> > +       .set_rxnfc              = i40evf_set_rxnfc,
>> > +       .get_rxfh_indir_size    = i40evf_get_rxfh_indir_size,
>> > +       .get_rxfh_indir         = i40evf_get_rxfh_indir,
>> > +       .set_rxfh_indir         = i40evf_set_rxfh_indir,
>> > +       .get_channels           = i40evf_get_channels,
>> >  };
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mitch Williams March 26, 2014, 7:21 p.m. UTC | #6
> -----Original Message-----

> From: Ben Hutchings [mailto:ben@decadent.org.uk]

> Sent: Monday, March 17, 2014 11:54 AM

> To: Kirsher, Jeffrey T

> Cc: davem@davemloft.net; Williams, Mitch A; netdev@vger.kernel.org;

> gospo@redhat.com; sassmann@redhat.com; Sullivan, Catherine

> Subject: Re: [net-next 03/16] i40evf: Support RSS option in ethtool

> 

> On Mon, 2014-03-17 at 05:45 -0700, Jeff Kirsher wrote:

> > From: Mitch Williams <mitch.a.williams@intel.com>

> >

> > Add support for viewing and modifying RSS hash options and RSS hash

> > look-up table programming through ethtool. Because the lookup table is

> > so small for the VFs (only 16 registers), we don't bother to maintain a

> > shadow table in memory, we just read and write the registers directly.

> [...]

> > +static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,

> > +				    struct ethtool_rxnfc *cmd)

> > +{

> > +	cmd->data = 0;

> > +

> > +	/* Report default options for RSS on i40e */

> 

> But you're allowing them to be changed from the defaults, so this is

> wrong.


Ben, I've got a question on this. Should the ETHTOOL_GRXFH option report what the driver and device are capable of, or should it report the current configuration? 

If this option is supposed to report device capabilities, how can we find out the current configuration? And if it's supposed to report the current configuration, then how do we find out the device capabilities?

I've been wading through the kernel source, and I see both. So I'm confused.

Currently, I have the i40evf driver just reporting capabilities, because I mostly swiped the code from i40e, which (I think) was swiped from ixgbe. (Note to any laywers reading this: "swiped" is a euphemism for "legally copied and/or adapted in compliance with all appropriate software licenses.)

What's your interpretation of how this should work? I'm respinning this for submittal upstream, and now's the time to change it if it needs to be changed.

Thanks,
Mitch
Ben Hutchings March 28, 2014, 12:14 a.m. UTC | #7
On Wed, 2014-03-26 at 19:21 +0000, Williams, Mitch A wrote:
> 
> > -----Original Message-----
> > From: Ben Hutchings [mailto:ben@decadent.org.uk]
> > Sent: Monday, March 17, 2014 11:54 AM
> > To: Kirsher, Jeffrey T
> > Cc: davem@davemloft.net; Williams, Mitch A; netdev@vger.kernel.org;
> > gospo@redhat.com; sassmann@redhat.com; Sullivan, Catherine
> > Subject: Re: [net-next 03/16] i40evf: Support RSS option in ethtool
> > 
> > On Mon, 2014-03-17 at 05:45 -0700, Jeff Kirsher wrote:
> > > From: Mitch Williams <mitch.a.williams@intel.com>
> > >
> > > Add support for viewing and modifying RSS hash options and RSS hash
> > > look-up table programming through ethtool. Because the lookup table is
> > > so small for the VFs (only 16 registers), we don't bother to maintain a
> > > shadow table in memory, we just read and write the registers directly.
> > [...]
> > > +static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
> > > +				    struct ethtool_rxnfc *cmd)
> > > +{
> > > +	cmd->data = 0;
> > > +
> > > +	/* Report default options for RSS on i40e */
> > 
> > But you're allowing them to be changed from the defaults, so this is
> > wrong.
> 
> Ben, I've got a question on this. Should the ETHTOOL_GRXFH option
> report what the driver and device are capable of, or should it report
> the current configuration? 

It should report the current configuration.

> If this option is supposed to report device capabilities, how can we
> find out the current configuration? And if it's supposed to report the
> current configuration, then how do we find out the device
> capabilities?

You can't find out the device capabilities except by trial and error (or
driver-specific documentation).  Even if ETHTOOL_GRXFH did tell you
which fields *could* be included in the hash, the structure doesn't have
space to tell you which subsets are supported.

> I've been wading through the kernel source, and I see both. So I'm
> confused.
[...]

The first implementation was in niu, and in the absence of accompanying
documentation that is what I took to define the interface and what I
attempted to document in <linux/ethtool.h>.  If you think the current
kernel-doc comment on struct ethtool_rxnfc is not clear enough, please
do send a patch to improve the wording.

Ben.
Mitch Williams March 28, 2014, 5:05 p.m. UTC | #8
> -----Original Message-----

> From: Ben Hutchings [mailto:ben@decadent.org.uk]

> Sent: Thursday, March 27, 2014 5:14 PM

> To: Williams, Mitch A

> Cc: Kirsher, Jeffrey T; davem@davemloft.net; netdev@vger.kernel.org;

> gospo@redhat.com; sassmann@redhat.com; Sullivan, Catherine

> Subject: Re: [net-next 03/16] i40evf: Support RSS option in ethtool

> 

> On Wed, 2014-03-26 at 19:21 +0000, Williams, Mitch A wrote:

> >

> > > -----Original Message-----

> > > From: Ben Hutchings [mailto:ben@decadent.org.uk]

> > > Sent: Monday, March 17, 2014 11:54 AM

> > > To: Kirsher, Jeffrey T

> > > Cc: davem@davemloft.net; Williams, Mitch A; netdev@vger.kernel.org;

> > > gospo@redhat.com; sassmann@redhat.com; Sullivan, Catherine

> > > Subject: Re: [net-next 03/16] i40evf: Support RSS option in ethtool

> > >

> > > On Mon, 2014-03-17 at 05:45 -0700, Jeff Kirsher wrote:

> > > > From: Mitch Williams <mitch.a.williams@intel.com>

> > > >

> > > > Add support for viewing and modifying RSS hash options and RSS hash

> > > > look-up table programming through ethtool. Because the lookup table is

> > > > so small for the VFs (only 16 registers), we don't bother to maintain

> a

> > > > shadow table in memory, we just read and write the registers directly.

> > > [...]

> > > > +static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,

> > > > +				    struct ethtool_rxnfc *cmd)

> > > > +{

> > > > +	cmd->data = 0;

> > > > +

> > > > +	/* Report default options for RSS on i40e */

> > >

> > > But you're allowing them to be changed from the defaults, so this is

> > > wrong.

> >

> > Ben, I've got a question on this. Should the ETHTOOL_GRXFH option

> > report what the driver and device are capable of, or should it report

> > the current configuration?

> 

> It should report the current configuration.

> 

> > If this option is supposed to report device capabilities, how can we

> > find out the current configuration? And if it's supposed to report the

> > current configuration, then how do we find out the device

> > capabilities?

> 

> You can't find out the device capabilities except by trial and error (or

> driver-specific documentation).  Even if ETHTOOL_GRXFH did tell you

> which fields *could* be included in the hash, the structure doesn't have

> space to tell you which subsets are supported.

> 

> > I've been wading through the kernel source, and I see both. So I'm

> > confused.

> [...]

> 

> The first implementation was in niu, and in the absence of accompanying

> documentation that is what I took to define the interface and what I

> attempted to document in <linux/ethtool.h>.  If you think the current

> kernel-doc comment on struct ethtool_rxnfc is not clear enough, please

> do send a patch to improve the wording.

> 


Thanks, Ben. I'll make sure that the i40evf driver does the right thing.

-Mitch

> Ben.

> 

> --

> Ben Hutchings

> 73.46% of all statistics are made up.
diff mbox

Patch

diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 8b0db1c..6a169aa 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -365,6 +365,315 @@  static int i40evf_set_coalesce(struct net_device *netdev,
 	return 0;
 }
 
+/**
+ * i40evf_get_rss_hash_opts - Get RSS hash Input Set for each flow type
+ * @adapter: board private structure
+ * @cmd: ethtool rxnfc command
+ *
+ * Returns Success if the flow is supported, else Invalid Input.
+ **/
+static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
+				    struct ethtool_rxnfc *cmd)
+{
+	cmd->data = 0;
+
+	/* Report default options for RSS on i40e */
+	switch (cmd->flow_type) {
+	case TCP_V4_FLOW:
+	case UDP_V4_FLOW:
+		cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+	/* fall through to add IP fields */
+	case SCTP_V4_FLOW:
+	case AH_ESP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case IPV4_FLOW:
+		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+		break;
+	case TCP_V6_FLOW:
+	case UDP_V6_FLOW:
+		cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+	/* fall through to add IP fields */
+	case SCTP_V6_FLOW:
+	case AH_ESP_V6_FLOW:
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+	case IPV6_FLOW:
+		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * i40evf_get_rxnfc - command to get RX flow classification rules
+ * @netdev: network interface device structure
+ * @cmd: ethtool rxnfc command
+ *
+ * Returns Success if the command is supported.
+ **/
+static int i40evf_get_rxnfc(struct net_device *netdev,
+			    struct ethtool_rxnfc *cmd,
+			    u32 *rule_locs)
+{
+	struct i40evf_adapter *adapter = netdev_priv(netdev);
+	int ret = -EOPNOTSUPP;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_GRXRINGS:
+		cmd->data = adapter->vsi_res->num_queue_pairs;
+		ret = 0;
+		break;
+	case ETHTOOL_GRXFH:
+		ret = i40evf_get_rss_hash_opts(adapter, cmd);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * i40evf_set_rss_hash_opt - Enable/Disable flow types for RSS hash
+ * @adapter: board private structure
+ * @cmd: ethtool rxnfc command
+ *
+ * Returns Success if the flow input set is supported.
+ **/
+static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
+				   struct ethtool_rxnfc *nfc)
+{
+	struct i40e_hw *hw = &adapter->hw;
+	u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) |
+		   ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32);
+
+	/* RSS does not support anything other than hashing
+	 * to queues on src and dst IPs and ports
+	 */
+	if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
+			  RXH_L4_B_0_1 | RXH_L4_B_2_3))
+		return -EINVAL;
+
+	/* We need at least the IP SRC and DEST fields for hashing */
+	if (!(nfc->data & RXH_IP_SRC) ||
+	    !(nfc->data & RXH_IP_DST))
+		return -EINVAL;
+
+	switch (nfc->flow_type) {
+	case TCP_V4_FLOW:
+		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+		case 0:
+			hena &= ~((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
+			break;
+		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+			hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case TCP_V6_FLOW:
+		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+		case 0:
+			hena &= ~((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
+			break;
+		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+			hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case UDP_V4_FLOW:
+		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+		case 0:
+			hena &=
+			~(((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
+			((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
+			((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4));
+			break;
+		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+			hena |=
+			(((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP)  |
+			((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
+			((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4));
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case UDP_V6_FLOW:
+		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+		case 0:
+			hena &=
+			~(((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
+			((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
+			((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6));
+			break;
+		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+			hena |=
+			(((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP)  |
+			((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
+			((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6));
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case AH_ESP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case SCTP_V4_FLOW:
+		if ((nfc->data & RXH_L4_B_0_1) ||
+		    (nfc->data & RXH_L4_B_2_3))
+			return -EINVAL;
+		hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER);
+		break;
+	case AH_ESP_V6_FLOW:
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+	case SCTP_V6_FLOW:
+		if ((nfc->data & RXH_L4_B_0_1) ||
+		    (nfc->data & RXH_L4_B_2_3))
+			return -EINVAL;
+		hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER);
+		break;
+	case IPV4_FLOW:
+		hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
+			((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4);
+		break;
+	case IPV6_FLOW:
+		hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
+			((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wr32(hw, I40E_VFQF_HENA(0), (u32)hena);
+	wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
+	i40e_flush(hw);
+
+	return 0;
+}
+
+/**
+ * i40evf_set_rxnfc - command to set RX flow classification rules
+ * @netdev: network interface device structure
+ * @cmd: ethtool rxnfc command
+ *
+ * Returns Success if the command is supported.
+ **/
+static int i40evf_set_rxnfc(struct net_device *netdev,
+			    struct ethtool_rxnfc *cmd)
+{
+	struct i40evf_adapter *adapter = netdev_priv(netdev);
+	int ret = -EOPNOTSUPP;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_SRXFH:
+		ret = i40evf_set_rss_hash_opt(adapter, cmd);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * i40evf_get_channels: get the number of channels supported by the device
+ * @netdev: network interface device structure
+ * @ch: channel information structure
+ *
+ * For the purposes of our device, we only use combined channels, i.e. a tx/rx
+ * queue pair. Report one extra channel to match our "other" MSI-X vector.
+ **/
+static void i40evf_get_channels(struct net_device *netdev,
+				struct ethtool_channels *ch)
+{
+	struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+	/* Report maximum channels */
+	ch->max_combined = adapter->vsi_res->num_queue_pairs;
+
+	ch->max_other = NONQ_VECS;
+	ch->other_count = NONQ_VECS;
+
+	ch->combined_count = adapter->vsi_res->num_queue_pairs;
+}
+
+/**
+ * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
+ * @netdev: network interface device structure
+ *
+ * Returns the table size.
+ **/
+static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
+{
+	return (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4;
+}
+
+/**
+ * i40evf_get_rxfh_indir - get the rx flow hash indirection table
+ * @netdev: network interface device structure
+ * @indir: indirection table
+ *
+ * Reads the indirection table directly from the hardware. Always returns 0.
+ **/
+static int i40evf_get_rxfh_indir(struct net_device *netdev, u32 *indir)
+{
+	struct i40evf_adapter *adapter = netdev_priv(netdev);
+	struct i40e_hw *hw = &adapter->hw;
+	u32 hlut_val;
+	int i, j;
+
+	for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX; i++) {
+		hlut_val = rd32(hw, I40E_VFQF_HLUT(i));
+		indir[j++] = hlut_val & 0xff;
+		indir[j++] = (hlut_val >> 8) & 0xff;
+		indir[j++] = (hlut_val >> 16) & 0xff;
+		indir[j++] = (hlut_val >> 24) & 0xff;
+	}
+	return 0;
+}
+
+/**
+ * i40evf_set_rxfh_indir - set the rx flow hash indirection table
+ * @netdev: network interface device structure
+ * @indir: indirection table
+ *
+ * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
+ * returns 0 after programming the table.
+ **/
+static int i40evf_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
+{
+	struct i40evf_adapter *adapter = netdev_priv(netdev);
+	struct i40e_hw *hw = &adapter->hw;
+	u32 hlut_val;
+	int i, j;
+
+	/* Verify user input. */
+	for (i = 0; i < (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4; i++) {
+		if (indir[i] >= adapter->vsi_res->num_queue_pairs)
+			return -EINVAL;
+	}
+
+	for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX + 1; i++) {
+		hlut_val = indir[j++];
+		hlut_val |= indir[j++] << 8;
+		hlut_val |= indir[j++] << 16;
+		hlut_val |= indir[j++] << 24;
+		wr32(hw, I40E_VFQF_HLUT(i), hlut_val);
+	}
+
+	return 0;
+}
+
 static struct ethtool_ops i40evf_ethtool_ops = {
 	.get_settings		= i40evf_get_settings,
 	.get_drvinfo		= i40evf_get_drvinfo,
@@ -378,6 +687,12 @@  static struct ethtool_ops i40evf_ethtool_ops = {
 	.set_msglevel		= i40evf_set_msglevel,
 	.get_coalesce		= i40evf_get_coalesce,
 	.set_coalesce		= i40evf_set_coalesce,
+	.get_rxnfc		= i40evf_get_rxnfc,
+	.set_rxnfc		= i40evf_set_rxnfc,
+	.get_rxfh_indir_size	= i40evf_get_rxfh_indir_size,
+	.get_rxfh_indir		= i40evf_get_rxfh_indir,
+	.set_rxfh_indir		= i40evf_set_rxfh_indir,
+	.get_channels		= i40evf_get_channels,
 };
 
 /**