diff mbox

[net-next-2.6,02/10] ethtool: add ntuple flow specifier to network flow classifier

Message ID 1298682048.3555.18.camel@localhost
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Ben Hutchings Feb. 26, 2011, 1 a.m. UTC
On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
> This change is meant to add an ntuple define type to the rx network flow
> classification specifiers.  The idea is to allow ntuple to be displayed and
> possibly configured via the network flow classification interface.  To do
> this I added a ntuple_flow_spec_ext to the lsit of supported filters, and
> added a flow_type_ext value to the structure in an unused hole within the
> ethtool_rx_flow_spec structure.

There's a hole there on 64-bit architectures.  Unfortunately, on i386
and other architectures where u64 is not 64-bit-aligned, there isn't.
We actually need to add compat handling for the commands that use it.

Also, we don't want these flags to be ignored by older kernel versions
and drivers - they should reject specs that they don't understand.  So
any extension flags need to be added to flow_type.

> Due to the fact that the flow specifier structures are only 4 byte aligned
> instead of 8 I had to break the user data field into 2 sections.  In
> addition I added the vlan ethertype field since this is what ixgbe was
> using the user-data for currently and it allows for the fields to stay 4
> byte aligned while occupying space at the end of the flow_spec.
>
> In order to guarantee byte ordering I also thought it best to keep all
> fields in the flow_spec area a big endian value, as such I added vlan, vlan
> ethertype, and data as big endian values.

It's not important that byte order is consistent across architectures.

> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
> 
>  include/linux/ethtool.h |   20 ++++++++++++++++++++
>  1 files changed, 20 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index aac3e2e..3d1f8e0 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
>  };
>  
>  /**
> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
> + * @unused: space unused by extension
> + * @vlan_etype: EtherType for vlan tagged packet to match
> + * @vlan_tci: VLAN tag to match
> + * @data: Driver-dependent data to match
> + */
> +struct ethtool_ntuple_spec_ext {
> +	__be32	unused[15];
> +	__be16	vlan_etype;
> +	__be16	vlan_tci;
> +	__be32	data[2];
> +};
[...]

This is a really nasty way to reclaim space in the union.

Let's name the union, shrink it and insert the extra fields that way:

---

Ben.

Comments

Alexander H Duyck Feb. 26, 2011, 5:30 a.m. UTC | #1
On Fri, Feb 25, 2011 at 5:00 PM, Ben Hutchings
<bhutchings@solarflare.com> wrote:
> On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
>> This change is meant to add an ntuple define type to the rx network flow
>> classification specifiers.  The idea is to allow ntuple to be displayed and
>> possibly configured via the network flow classification interface.  To do
>> this I added a ntuple_flow_spec_ext to the lsit of supported filters, and
>> added a flow_type_ext value to the structure in an unused hole within the
>> ethtool_rx_flow_spec structure.
>
> There's a hole there on 64-bit architectures.  Unfortunately, on i386
> and other architectures where u64 is not 64-bit-aligned, there isn't.
> We actually need to add compat handling for the commands that use it.
>
> Also, we don't want these flags to be ignored by older kernel versions
> and drivers - they should reject specs that they don't understand.  So
> any extension flags need to be added to flow_type.
>
>> Due to the fact that the flow specifier structures are only 4 byte aligned
>> instead of 8 I had to break the user data field into 2 sections.  In
>> addition I added the vlan ethertype field since this is what ixgbe was
>> using the user-data for currently and it allows for the fields to stay 4
>> byte aligned while occupying space at the end of the flow_spec.
>>
>> In order to guarantee byte ordering I also thought it best to keep all
>> fields in the flow_spec area a big endian value, as such I added vlan, vlan
>> ethertype, and data as big endian values.
>
> It's not important that byte order is consistent across architectures.
>
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>> ---
>>
>>  include/linux/ethtool.h |   20 ++++++++++++++++++++
>>  1 files changed, 20 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index aac3e2e..3d1f8e0 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
>>  };
>>
>>  /**
>> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
>> + * @unused: space unused by extension
>> + * @vlan_etype: EtherType for vlan tagged packet to match
>> + * @vlan_tci: VLAN tag to match
>> + * @data: Driver-dependent data to match
>> + */
>> +struct ethtool_ntuple_spec_ext {
>> +     __be32  unused[15];
>> +     __be16  vlan_etype;
>> +     __be16  vlan_tci;
>> +     __be32  data[2];
>> +};
> [...]
>
> This is a really nasty way to reclaim space in the union.
>
> Let's name the union, shrink it and insert the extra fields that way:
>
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
>        __u8    proto;
>  };
>
> +union ethtool_flow_union {
> +       struct ethtool_tcpip4_spec              tcp_ip4_spec;
> +       struct ethtool_tcpip4_spec              udp_ip4_spec;
> +       struct ethtool_tcpip4_spec              sctp_ip4_spec;
> +       struct ethtool_ah_espip4_spec           ah_ip4_spec;
> +       struct ethtool_ah_espip4_spec           esp_ip4_spec;
> +       struct ethtool_usrip4_spec              usr_ip4_spec;
> +       struct ethhdr                           ether_spec;
> +       __u8                                    hdata[52];
> +};
> +
> +struct ethtool_flow_ext {
> +       __be16  vlan_etype;
> +       __be16  vlan_tci;
> +       __be32  data[2];
> +       __u32   reserved[2];
> +};
> +

Any chance of getting the reserved fields moved to the top of the
structure?  My only concern is that we might end up with a flow spec
larger than 52 bytes at some point and moving the reserved fields to
the front might give us a little more wiggle room future
compatibility.

>  /**
>  * struct ethtool_rx_flow_spec - specification for RX flow filter
>  * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
>  * @h_u: Flow fields to match (dependent on @flow_type)
> + * @h_ext: Additional fields to match
>  * @m_u: Masks for flow field bits to be ignored
> + * @m_ext: Masks for additional field bits to be ignored.
> + *     Note, all additional fields must be ignored unless @flow_type
> + *     includes the %FLOW_EXT flag.
>  * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
>  *     if packets should be discarded
>  * @location: Index of filter in hardware table
>  */
>  struct ethtool_rx_flow_spec {
>        __u32           flow_type;
> -       union {
> -               struct ethtool_tcpip4_spec              tcp_ip4_spec;
> -               struct ethtool_tcpip4_spec              udp_ip4_spec;
> -               struct ethtool_tcpip4_spec              sctp_ip4_spec;
> -               struct ethtool_ah_espip4_spec           ah_ip4_spec;
> -               struct ethtool_ah_espip4_spec           esp_ip4_spec;
> -               struct ethtool_usrip4_spec              usr_ip4_spec;
> -               struct ethhdr                           ether_spec;
> -               __u8                                    hdata[72];
> -       } h_u, m_u;
> +       union ethtool_flow_union h_u;
> +       struct ethtool_flow_ext h_ext;
> +       union ethtool_flow_union m_u;
> +       struct ethtool_flow_ext m_ext;
>        __u64           ring_cookie;
>        __u32           location;
>  };
> @@ -954,6 +970,8 @@ struct ethtool_ops {
>  #define        IPV4_FLOW       0x10    /* hash only */
>  #define        IPV6_FLOW       0x11    /* hash only */
>  #define        ETHER_FLOW      0x12    /* spec only (ether_spec) */
> +/* Flag to enable additional fields in struct ethtool_rx_flow_spec */
> +#define        FLOW_EXT        0x80000000
>
>  /* L3-L4 network traffic flow hash options */
>  #define        RXH_L2DA        (1 << 1)
> ---
>
> Ben.

This works for my purposes other than the one comment above.  However
if you are fine with it I am good with it since I can't think of any
filters that we might need in the near future that would require more
than 52 bytes.

Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
--
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 2, 2011, 6:50 p.m. UTC | #2
On Fri, 2011-02-25 at 21:30 -0800, Alexander Duyck wrote:
> On Fri, Feb 25, 2011 at 5:00 PM, Ben Hutchings
> <bhutchings@solarflare.com> wrote:
> > On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
[...]
> >> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> >> index aac3e2e..3d1f8e0 100644
> >> --- a/include/linux/ethtool.h
> >> +++ b/include/linux/ethtool.h
> >> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
> >>  };
> >>
> >>  /**
> >> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
> >> + * @unused: space unused by extension
> >> + * @vlan_etype: EtherType for vlan tagged packet to match
> >> + * @vlan_tci: VLAN tag to match
> >> + * @data: Driver-dependent data to match
> >> + */
> >> +struct ethtool_ntuple_spec_ext {
> >> +     __be32  unused[15];
> >> +     __be16  vlan_etype;
> >> +     __be16  vlan_tci;
> >> +     __be32  data[2];
> >> +};
> > [...]
> >
> > This is a really nasty way to reclaim space in the union.
> >
> > Let's name the union, shrink it and insert the extra fields that way:
> >
> > --- a/include/linux/ethtool.h
> > +++ b/include/linux/ethtool.h
> > @@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
> >        __u8    proto;
> >  };
> >
> > +union ethtool_flow_union {
> > +       struct ethtool_tcpip4_spec              tcp_ip4_spec;
> > +       struct ethtool_tcpip4_spec              udp_ip4_spec;
> > +       struct ethtool_tcpip4_spec              sctp_ip4_spec;
> > +       struct ethtool_ah_espip4_spec           ah_ip4_spec;
> > +       struct ethtool_ah_espip4_spec           esp_ip4_spec;
> > +       struct ethtool_usrip4_spec              usr_ip4_spec;
> > +       struct ethhdr                           ether_spec;
> > +       __u8                                    hdata[52];
> > +};
> > +
> > +struct ethtool_flow_ext {
> > +       __be16  vlan_etype;
> > +       __be16  vlan_tci;
> > +       __be32  data[2];
> > +       __u32   reserved[2];
> > +};
> > +
> 
> Any chance of getting the reserved fields moved to the top of the
> structure?  My only concern is that we might end up with a flow spec
> larger than 52 bytes at some point and moving the reserved fields to
> the front might give us a little more wiggle room future
> compatibility.
[...]

OK, so how about this:

/**
 * union ethtool_flow_union - flow spec type-specific fields
 * @tcp_ip4_spec: TCP/IPv4 fields to match
 * @udp_ip4_spec: UDP/IPv4 fields to match
 * @sctp_ip4_spec: SCTP/IPv4 fields to match 
 * @ah_ip4_spec: AH/IPv4 fields to match
 * @esp_ip4_spec: ESP/IPv4 fields to match
 * @usr_ip4_spec: User-defined IPv4 fields to match
 * @ether_spec: Ethernet fields to match
 *
 * Note: The size of this union may shrink in future to allow for
 * expansion in &struct ethtool_flow_ext.
 */
union ethtool_flow_union {
	struct ethtool_tcpip4_spec		tcp_ip4_spec;
	struct ethtool_tcpip4_spec		udp_ip4_spec;
	struct ethtool_tcpip4_spec		sctp_ip4_spec;
	struct ethtool_ah_espip4_spec		ah_ip4_spec;
	struct ethtool_ah_espip4_spec		esp_ip4_spec;
	struct ethtool_usrip4_spec		usr_ip4_spec;
	struct ethhdr				ether_spec;
	__u8					hdata[60];
};

/**
 * struct ethtool_flow_ext - flow spec common extension fields
 * @vlan_etype: EtherType for vlan tagged packet to match
 * @vlan_tci: VLAN tag to match
 * @data: Driver-dependent data to match
 *
 * Note: Additional fields may be inserted before @vlan_etype in future,
 * but the offset of the existing fields within the containing structure
 * (&struct ethtool_rx_flow_spec) will be stable.
 */
struct ethtool_flow_ext {
	__be16	vlan_etype;
	__be16	vlan_tci;
	__be32	data[2];
};

Please can you check that these definitions won't affect the size of
struct ethtool_rx_flow_spec on i386 or x86-64?

Ben.
Ben Hutchings March 2, 2011, 7:27 p.m. UTC | #3
On Wed, 2011-03-02 at 11:11 -0800, Dimitrios Michailidis wrote:
> Ben Hutchings wrote:
> > /**
> >  * struct ethtool_flow_ext - flow spec common extension fields
> >  * @vlan_etype: EtherType for vlan tagged packet to match
> >  * @vlan_tci: VLAN tag to match
> >  * @data: Driver-dependent data to match
> >  *
> >  * Note: Additional fields may be inserted before @vlan_etype in future,
> >  * but the offset of the existing fields within the containing structure
> >  * (&struct ethtool_rx_flow_spec) will be stable.
> >  */
> > struct ethtool_flow_ext {
> > 	__be16	vlan_etype;
> > 	__be16	vlan_tci;
> > 	__be32	data[2];
> > };
> 
> I am wondering about the semantics of these vlan_* fields.  Is vlan_etype the
> Ethertype in the VLAN header or the type after it?

It would be the the type in the VLAN tag.  The nested ethertype is
normally implied by flow_type to be ETH_P_IP.

This does leave the question of what this would mean:

struct ethtool_rx_flow_spec fs = {
	.flow_type = ... | FLOW_EXT,
	...
	.h_ext.vlan_tci = htons(0x1234),
	.m_ext.vlan_etype = 0xffff,
};

This says the TCI must be == 0x1234 but the type can be anything.  But
the type surely has to be be one assigned for use in VLAN tags.  Should
we leave it to the driver/hardware to determine what those valid types
are, or should we reject this as valid?

> Specifically, I am wondering
> whether these fields are limited to VLANs or can work with general Ethertypes and the
> 2 bytes after them.

If you set flow_type = ETHER_FLOW you can then specify any combination
of Ethernet header fields to match in {h_u,m_u}.ether_spec.  However, so
far only sfc implements it and it only allows matching on the
destination MAC address.

Ben.
Duyck, Alexander H March 4, 2011, 7:30 p.m. UTC | #4
On 3/2/2011 12:03 PM, Dimitrios Michailidis wrote:
> Ben Hutchings wrote:
>> On Wed, 2011-03-02 at 11:11 -0800, Dimitrios Michailidis wrote:
>>> Ben Hutchings wrote:
>>>> /**
>>>>   * struct ethtool_flow_ext - flow spec common extension fields
>>>>   * @vlan_etype: EtherType for vlan tagged packet to match
>>>>   * @vlan_tci: VLAN tag to match
>>>>   * @data: Driver-dependent data to match
>>>>   *
>>>>   * Note: Additional fields may be inserted before @vlan_etype in future,
>>>>   * but the offset of the existing fields within the containing structure
>>>>   * (&struct ethtool_rx_flow_spec) will be stable.
>>>>   */
>>>> struct ethtool_flow_ext {
>>>> 	__be16	vlan_etype;
>>>> 	__be16	vlan_tci;
>>>> 	__be32	data[2];
>>>> };
>>>
>>> I am wondering about the semantics of these vlan_* fields.  Is vlan_etype the
>>> Ethertype in the VLAN header or the type after it?
>>
>> It would be the the type in the VLAN tag.  The nested ethertype is
>> normally implied by flow_type to be ETH_P_IP.
>>
>> This does leave the question of what this would mean:
>>
>> struct ethtool_rx_flow_spec fs = {
>> 	.flow_type = ... | FLOW_EXT,
>> 	...
>> 	.h_ext.vlan_tci = htons(0x1234),
>> 	.m_ext.vlan_etype = 0xffff,
>> };
>>
>> This says the TCI must be == 0x1234 but the type can be anything.  But
>> the type surely has to be be one assigned for use in VLAN tags.  Should
>> we leave it to the driver/hardware to determine what those valid types
>> are, or should we reject this as valid?
>
> Right.  Devices have some internal rules for what qualifies as a VLAN frame.
> If users are given the option to specify vlan_etype what do they get?
> At least we need to specify what is expected so drivers can decide if they can support it.

The basic idea I had is similar to what Ben described.  Basically the 
vlan_etype can be used to determine the Ethertype for the VLAN to be 
compared.  The reason for this is specifically the VLAN 0 case since 
without the VLAN Ethertype check VLAN 0 on ixgbe hardware will match an 
untagged frame and that may not be a desired result.  As such we can 
specify the VLAN Ethertype and then we will only match VLAN tagged 
frames without any false hits.

Thanks,

Alex

--
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
Duyck, Alexander H March 4, 2011, 9 p.m. UTC | #5
On 3/2/2011 10:50 AM, Ben Hutchings wrote:
> On Fri, 2011-02-25 at 21:30 -0800, Alexander Duyck wrote:
>> On Fri, Feb 25, 2011 at 5:00 PM, Ben Hutchings
>> <bhutchings@solarflare.com>  wrote:
>>> On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
> [...]
>>>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>>>> index aac3e2e..3d1f8e0 100644
>>>> --- a/include/linux/ethtool.h
>>>> +++ b/include/linux/ethtool.h
>>>> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
>>>>   };
>>>>
>>>>   /**
>>>> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
>>>> + * @unused: space unused by extension
>>>> + * @vlan_etype: EtherType for vlan tagged packet to match
>>>> + * @vlan_tci: VLAN tag to match
>>>> + * @data: Driver-dependent data to match
>>>> + */
>>>> +struct ethtool_ntuple_spec_ext {
>>>> +     __be32  unused[15];
>>>> +     __be16  vlan_etype;
>>>> +     __be16  vlan_tci;
>>>> +     __be32  data[2];
>>>> +};
>>> [...]
>>>
>>> This is a really nasty way to reclaim space in the union.
>>>
>>> Let's name the union, shrink it and insert the extra fields that way:
>>>
>>> --- a/include/linux/ethtool.h
>>> +++ b/include/linux/ethtool.h
>>> @@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
>>>         __u8    proto;
>>>   };
>>>
>>> +union ethtool_flow_union {
>>> +       struct ethtool_tcpip4_spec              tcp_ip4_spec;
>>> +       struct ethtool_tcpip4_spec              udp_ip4_spec;
>>> +       struct ethtool_tcpip4_spec              sctp_ip4_spec;
>>> +       struct ethtool_ah_espip4_spec           ah_ip4_spec;
>>> +       struct ethtool_ah_espip4_spec           esp_ip4_spec;
>>> +       struct ethtool_usrip4_spec              usr_ip4_spec;
>>> +       struct ethhdr                           ether_spec;
>>> +       __u8                                    hdata[52];
>>> +};
>>> +
>>> +struct ethtool_flow_ext {
>>> +       __be16  vlan_etype;
>>> +       __be16  vlan_tci;
>>> +       __be32  data[2];
>>> +       __u32   reserved[2];
>>> +};
>>> +
>>
>> Any chance of getting the reserved fields moved to the top of the
>> structure?  My only concern is that we might end up with a flow spec
>> larger than 52 bytes at some point and moving the reserved fields to
>> the front might give us a little more wiggle room future
>> compatibility.
> [...]
>
> OK, so how about this:
>
> /**
>   * union ethtool_flow_union - flow spec type-specific fields
>   * @tcp_ip4_spec: TCP/IPv4 fields to match
>   * @udp_ip4_spec: UDP/IPv4 fields to match
>   * @sctp_ip4_spec: SCTP/IPv4 fields to match
>   * @ah_ip4_spec: AH/IPv4 fields to match
>   * @esp_ip4_spec: ESP/IPv4 fields to match
>   * @usr_ip4_spec: User-defined IPv4 fields to match
>   * @ether_spec: Ethernet fields to match
>   *
>   * Note: The size of this union may shrink in future to allow for
>   * expansion in&struct ethtool_flow_ext.
>   */
> union ethtool_flow_union {
> 	struct ethtool_tcpip4_spec		tcp_ip4_spec;
> 	struct ethtool_tcpip4_spec		udp_ip4_spec;
> 	struct ethtool_tcpip4_spec		sctp_ip4_spec;
> 	struct ethtool_ah_espip4_spec		ah_ip4_spec;
> 	struct ethtool_ah_espip4_spec		esp_ip4_spec;
> 	struct ethtool_usrip4_spec		usr_ip4_spec;
> 	struct ethhdr				ether_spec;
> 	__u8					hdata[60];
> };
>
> /**
>   * struct ethtool_flow_ext - flow spec common extension fields
>   * @vlan_etype: EtherType for vlan tagged packet to match
>   * @vlan_tci: VLAN tag to match
>   * @data: Driver-dependent data to match
>   *
>   * Note: Additional fields may be inserted before @vlan_etype in future,
>   * but the offset of the existing fields within the containing structure
>   * (&struct ethtool_rx_flow_spec) will be stable.
>   */
> struct ethtool_flow_ext {
> 	__be16	vlan_etype;
> 	__be16	vlan_tci;
> 	__be32	data[2];
> };
>
> Please can you check that these definitions won't affect the size of
> struct ethtool_rx_flow_spec on i386 or x86-64?
>
> Ben.
>


I'll try to look into it next week since I am just getting caught up 
from being out on vacation.

As I recall when I had made my original changes they didn't have an 
effect on the size so this should be fine since all of the fields have a 
maximum alignment of 32 bits.

Thanks,

Alex
--
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
diff mbox

Patch

--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -377,27 +377,43 @@  struct ethtool_usrip4_spec {
 	__u8    proto;
 };
 
+union ethtool_flow_union {
+	struct ethtool_tcpip4_spec		tcp_ip4_spec;
+	struct ethtool_tcpip4_spec		udp_ip4_spec;
+	struct ethtool_tcpip4_spec		sctp_ip4_spec;
+	struct ethtool_ah_espip4_spec		ah_ip4_spec;
+	struct ethtool_ah_espip4_spec		esp_ip4_spec;
+	struct ethtool_usrip4_spec		usr_ip4_spec;
+	struct ethhdr				ether_spec;
+	__u8					hdata[52];
+};
+
+struct ethtool_flow_ext {
+	__be16	vlan_etype;
+	__be16	vlan_tci;
+	__be32	data[2];
+	__u32	reserved[2];
+};
+
 /**
  * struct ethtool_rx_flow_spec - specification for RX flow filter
  * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
  * @h_u: Flow fields to match (dependent on @flow_type)
+ * @h_ext: Additional fields to match
  * @m_u: Masks for flow field bits to be ignored
+ * @m_ext: Masks for additional field bits to be ignored.
+ *	Note, all additional fields must be ignored unless @flow_type
+ *	includes the %FLOW_EXT flag.
  * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
  *	if packets should be discarded
  * @location: Index of filter in hardware table
  */
 struct ethtool_rx_flow_spec {
 	__u32		flow_type;
-	union {
-		struct ethtool_tcpip4_spec		tcp_ip4_spec;
-		struct ethtool_tcpip4_spec		udp_ip4_spec;
-		struct ethtool_tcpip4_spec		sctp_ip4_spec;
-		struct ethtool_ah_espip4_spec		ah_ip4_spec;
-		struct ethtool_ah_espip4_spec		esp_ip4_spec;
-		struct ethtool_usrip4_spec		usr_ip4_spec;
-		struct ethhdr				ether_spec;
-		__u8					hdata[72];
-	} h_u, m_u;
+	union ethtool_flow_union h_u;
+	struct ethtool_flow_ext h_ext;
+	union ethtool_flow_union m_u;
+	struct ethtool_flow_ext m_ext;
 	__u64		ring_cookie;
 	__u32		location;
 };
@@ -954,6 +970,8 @@  struct ethtool_ops {
 #define	IPV4_FLOW	0x10	/* hash only */
 #define	IPV6_FLOW	0x11	/* hash only */
 #define	ETHER_FLOW	0x12	/* spec only (ether_spec) */
+/* Flag to enable additional fields in struct ethtool_rx_flow_spec */
+#define	FLOW_EXT	0x80000000
 
 /* L3-L4 network traffic flow hash options */
 #define	RXH_L2DA	(1 << 1)