diff mbox

[net-next,08/14] ixgbe: Add support for generic Tx checksums

Message ID 1459808097-26409-9-git-send-email-jeffrey.t.kirsher@intel.com
State Changes Requested, archived
Headers show

Commit Message

Kirsher, Jeffrey T April 4, 2016, 10:14 p.m. UTC
From: Alexander Duyck <aduyck@mirantis.com>

This patch adds support for generic Tx checksums to the ixgbe driver.  It
turns out this is actually pretty easy after going over the datasheet as we
were doing a number of steps we didn't need to.

In order to perform a Tx checksum for an L4 header we need to fill in the
following fields in the Tx descriptor:
  MACLEN (maximum of 127), retrieved from:
		skb_network_offset()
  IPLEN  (maximum of 511), retrieved from:
		skb_checksum_start_offset() - skb_network_offset()
  TUCMD.L4T indicates offset and if checksum or crc32c, based on:
		skb->csum_offset

The added advantage to doing this is that we can support inner checksum
offloads for tunnels and MPLS while still being able to transparently
insert VLAN tags.

I also took the opportunity to clean-up many of the feature flag
configuration bits to make them a bit more consistent between drivers.

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 164 +++++++++-----------------
 1 file changed, 59 insertions(+), 105 deletions(-)

Comments

Samudrala, Sridhar April 4, 2016, 10:32 p.m. UTC | #1
On 4/4/2016 3:14 PM, Jeff Kirsher wrote:
> From: Alexander Duyck <aduyck@mirantis.com>
>
> This patch adds support for generic Tx checksums to the ixgbe driver.  It
> turns out this is actually pretty easy after going over the datasheet as we
> were doing a number of steps we didn't need to.
>
> In order to perform a Tx checksum for an L4 header we need to fill in the
> following fields in the Tx descriptor:
>    MACLEN (maximum of 127), retrieved from:
> 		skb_network_offset()
>    IPLEN  (maximum of 511), retrieved from:
> 		skb_checksum_start_offset() - skb_network_offset()
>    TUCMD.L4T indicates offset and if checksum or crc32c, based on:
> 		skb->csum_offset
>
> The added advantage to doing this is that we can support inner checksum
> offloads for tunnels and MPLS while still being able to transparently
> insert VLAN tags.
>
> I also took the opportunity to clean-up many of the feature flag
> configuration bits to make them a bit more consistent between drivers.
>
> Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 164 +++++++++-----------------
>   1 file changed, 59 insertions(+), 105 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index bce5737..8d248c8 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -7202,103 +7202,61 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
>   	return 1;
>   }
>   

<snip>


> @@ -9190,41 +9148,37 @@ skip_sriov:
>   
>   #endif
>   	netdev->features = NETIF_F_SG |
> -			   NETIF_F_IP_CSUM |
> -			   NETIF_F_IPV6_CSUM |
> -			   NETIF_F_HW_VLAN_CTAG_TX |
> -			   NETIF_F_HW_VLAN_CTAG_RX |
>   			   NETIF_F_TSO |
>   			   NETIF_F_TSO6 |
>   			   NETIF_F_RXHASH |
> -			   NETIF_F_RXCSUM;
> -
> -	netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
> +			   NETIF_F_RXCSUM |
> +			   NETIF_F_HW_CSUM |
> +			   NETIF_F_SCTP_CRC |
> +			   NETIF_F_HW_VLAN_CTAG_TX |
> +			   NETIF_F_HW_VLAN_CTAG_RX;
>   
> -	switch (adapter->hw.mac.type) {
> -	case ixgbe_mac_82599EB:
> -	case ixgbe_mac_X540:
> -	case ixgbe_mac_X550:
> -	case ixgbe_mac_X550EM_x:
> +	if (hw->mac.type >= ixgbe_mac_82599EB)
>   		netdev->features |= NETIF_F_SCTP_CRC;
> -		netdev->hw_features |= NETIF_F_SCTP_CRC |
> -				       NETIF_F_NTUPLE |
> -				       NETIF_F_HW_TC;
> -		break;
> -	default:
> -		break;
> -	}
>   
> -	netdev->hw_features |= NETIF_F_RXALL;
> +	/* copy netdev features into list of user selectable features */
> +	netdev->hw_features |= netdev->features;
> +	netdev->hw_features |= NETIF_F_RXALL |
> +			       NETIF_F_HW_L2FW_DOFFLOAD;
> +
> +	if (hw->mac.type >= ixgbe_mac_82599EB)
> +		netdev->hw_features |= NETIF_F_NTUPLE;

looks like the cleanup missed moving NETIF_F_HW_TC flag here that 
enables cls_u32 offloads via TC.

> +
> +	/* set this bit last since it cannot be part of hw_features */
>   	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
>   
> -	netdev->vlan_features |= NETIF_F_TSO;
> -	netdev->vlan_features |= NETIF_F_TSO6;
> -	netdev->vlan_features |= NETIF_F_IP_CSUM;
> -	netdev->vlan_features |= NETIF_F_IPV6_CSUM;
> -	netdev->vlan_features |= NETIF_F_SG;
> +	netdev->vlan_features |= NETIF_F_SG |
> +				 NETIF_F_TSO |
> +				 NETIF_F_TSO6 |
> +				 NETIF_F_HW_CSUM |
> +				 NETIF_F_SCTP_CRC;
>   
> -	netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
> +	netdev->mpls_features |= NETIF_F_HW_CSUM;
> +	netdev->hw_enc_features |= NETIF_F_HW_CSUM;
>   
>   	netdev->priv_flags |= IFF_UNICAST_FLT;
>   	netdev->priv_flags |= IFF_SUPP_NOFCS;
Alexander H Duyck April 4, 2016, 10:54 p.m. UTC | #2
On Mon, Apr 4, 2016 at 3:32 PM, Samudrala, Sridhar
<sridhar.samudrala@intel.com> wrote:
> On 4/4/2016 3:14 PM, Jeff Kirsher wrote:
>>
>> From: Alexander Duyck <aduyck@mirantis.com>
>>
>> This patch adds support for generic Tx checksums to the ixgbe driver.  It
>> turns out this is actually pretty easy after going over the datasheet as
>> we
>> were doing a number of steps we didn't need to.
>>
>> In order to perform a Tx checksum for an L4 header we need to fill in the
>> following fields in the Tx descriptor:
>>    MACLEN (maximum of 127), retrieved from:
>>                 skb_network_offset()
>>    IPLEN  (maximum of 511), retrieved from:
>>                 skb_checksum_start_offset() - skb_network_offset()
>>    TUCMD.L4T indicates offset and if checksum or crc32c, based on:
>>                 skb->csum_offset
>>
>> The added advantage to doing this is that we can support inner checksum
>> offloads for tunnels and MPLS while still being able to transparently
>> insert VLAN tags.
>>
>> I also took the opportunity to clean-up many of the feature flag
>> configuration bits to make them a bit more consistent between drivers.
>>
>> Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
>> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> ---
>>   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 164
>> +++++++++-----------------
>>   1 file changed, 59 insertions(+), 105 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> index bce5737..8d248c8 100644
>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> @@ -7202,103 +7202,61 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
>>         return 1;
>>   }
>>
>
>
> <snip>
>
>
>
>> @@ -9190,41 +9148,37 @@ skip_sriov:
>>     #endif
>>         netdev->features = NETIF_F_SG |
>> -                          NETIF_F_IP_CSUM |
>> -                          NETIF_F_IPV6_CSUM |
>> -                          NETIF_F_HW_VLAN_CTAG_TX |
>> -                          NETIF_F_HW_VLAN_CTAG_RX |
>>                            NETIF_F_TSO |
>>                            NETIF_F_TSO6 |
>>                            NETIF_F_RXHASH |
>> -                          NETIF_F_RXCSUM;
>> -
>> -       netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
>> +                          NETIF_F_RXCSUM |
>> +                          NETIF_F_HW_CSUM |
>> +                          NETIF_F_SCTP_CRC |
>> +                          NETIF_F_HW_VLAN_CTAG_TX |
>> +                          NETIF_F_HW_VLAN_CTAG_RX;
>>   -     switch (adapter->hw.mac.type) {
>> -       case ixgbe_mac_82599EB:
>> -       case ixgbe_mac_X540:
>> -       case ixgbe_mac_X550:
>> -       case ixgbe_mac_X550EM_x:
>> +       if (hw->mac.type >= ixgbe_mac_82599EB)
>>                 netdev->features |= NETIF_F_SCTP_CRC;
>> -               netdev->hw_features |= NETIF_F_SCTP_CRC |
>> -                                      NETIF_F_NTUPLE |
>> -                                      NETIF_F_HW_TC;
>> -               break;
>> -       default:
>> -               break;
>> -       }
>>   -     netdev->hw_features |= NETIF_F_RXALL;
>> +       /* copy netdev features into list of user selectable features */
>> +       netdev->hw_features |= netdev->features;
>> +       netdev->hw_features |= NETIF_F_RXALL |
>> +                              NETIF_F_HW_L2FW_DOFFLOAD;
>> +
>> +       if (hw->mac.type >= ixgbe_mac_82599EB)
>> +               netdev->hw_features |= NETIF_F_NTUPLE;
>
>
> looks like the cleanup missed moving NETIF_F_HW_TC flag here that enables
> cls_u32 offloads via TC.

Back when I submitted this patch the NETIF_F_HW_TC flag didn't exist.
I'm pretty sure this is probably a case of a patch getting mangled
after sitting in the tree for so long.

In addition I just noticed there is a bug in the setting of the
SCTP_CRC flag as well.  It is set twice when we should only be setting
it in the if statement.  It is just a quick 2 line fix that is needed.
I can either submit a follow-up or I can respin the original patch
real quick so that it applies on top of the current ixgbe queue.

- Alex
Kirsher, Jeffrey T April 4, 2016, 10:56 p.m. UTC | #3
On Mon, 2016-04-04 at 15:54 -0700, Alexander Duyck wrote:
> On Mon, Apr 4, 2016 at 3:32 PM, Samudrala, Sridhar
> <sridhar.samudrala@intel.com> wrote:
> > On 4/4/2016 3:14 PM, Jeff Kirsher wrote:
> >>
> >> From: Alexander Duyck <aduyck@mirantis.com>
> >>
> >> This patch adds support for generic Tx checksums to the ixgbe
> driver.  It
> >> turns out this is actually pretty easy after going over the
> datasheet as
> >> we
> >> were doing a number of steps we didn't need to.
> >>
> >> In order to perform a Tx checksum for an L4 header we need to fill
> in the
> >> following fields in the Tx descriptor:
> >>    MACLEN (maximum of 127), retrieved from:
> >>                 skb_network_offset()
> >>    IPLEN  (maximum of 511), retrieved from:
> >>                 skb_checksum_start_offset() - skb_network_offset()
> >>    TUCMD.L4T indicates offset and if checksum or crc32c, based on:
> >>                 skb->csum_offset
> >>
> >> The added advantage to doing this is that we can support inner
> checksum
> >> offloads for tunnels and MPLS while still being able to
> transparently
> >> insert VLAN tags.
> >>
> >> I also took the opportunity to clean-up many of the feature flag
> >> configuration bits to make them a bit more consistent between
> drivers.
> >>
> >> Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
> >> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
> >> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> >> ---
> >>   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 164
> >> +++++++++-----------------
> >>   1 file changed, 59 insertions(+), 105 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> >> b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> >> index bce5737..8d248c8 100644
> >> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> >> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> >> @@ -7202,103 +7202,61 @@ static int ixgbe_tso(struct ixgbe_ring
> *tx_ring,
> >>         return 1;
> >>   }
> >>
> >
> >
> > <snip>
> >
> >
> >
> >> @@ -9190,41 +9148,37 @@ skip_sriov:
> >>     #endif
> >>         netdev->features = NETIF_F_SG |
> >> -                          NETIF_F_IP_CSUM |
> >> -                          NETIF_F_IPV6_CSUM |
> >> -                          NETIF_F_HW_VLAN_CTAG_TX |
> >> -                          NETIF_F_HW_VLAN_CTAG_RX |
> >>                            NETIF_F_TSO |
> >>                            NETIF_F_TSO6 |
> >>                            NETIF_F_RXHASH |
> >> -                          NETIF_F_RXCSUM;
> >> -
> >> -       netdev->hw_features = netdev->features |
> NETIF_F_HW_L2FW_DOFFLOAD;
> >> +                          NETIF_F_RXCSUM |
> >> +                          NETIF_F_HW_CSUM |
> >> +                          NETIF_F_SCTP_CRC |
> >> +                          NETIF_F_HW_VLAN_CTAG_TX |
> >> +                          NETIF_F_HW_VLAN_CTAG_RX;
> >>   -     switch (adapter->hw.mac.type) {
> >> -       case ixgbe_mac_82599EB:
> >> -       case ixgbe_mac_X540:
> >> -       case ixgbe_mac_X550:
> >> -       case ixgbe_mac_X550EM_x:
> >> +       if (hw->mac.type >= ixgbe_mac_82599EB)
> >>                 netdev->features |= NETIF_F_SCTP_CRC;
> >> -               netdev->hw_features |= NETIF_F_SCTP_CRC |
> >> -                                      NETIF_F_NTUPLE |
> >> -                                      NETIF_F_HW_TC;
> >> -               break;
> >> -       default:
> >> -               break;
> >> -       }
> >>   -     netdev->hw_features |= NETIF_F_RXALL;
> >> +       /* copy netdev features into list of user selectable
> features */
> >> +       netdev->hw_features |= netdev->features;
> >> +       netdev->hw_features |= NETIF_F_RXALL |
> >> +                              NETIF_F_HW_L2FW_DOFFLOAD;
> >> +
> >> +       if (hw->mac.type >= ixgbe_mac_82599EB)
> >> +               netdev->hw_features |= NETIF_F_NTUPLE;
> >
> >
> > looks like the cleanup missed moving NETIF_F_HW_TC flag here that
> enables
> > cls_u32 offloads via TC.
> 
> Back when I submitted this patch the NETIF_F_HW_TC flag didn't exist.
> I'm pretty sure this is probably a case of a patch getting mangled
> after sitting in the tree for so long.
> 
> In addition I just noticed there is a bug in the setting of the
> SCTP_CRC flag as well.  It is set twice when we should only be
> setting
> it in the if statement.  It is just a quick 2 line fix that is
> needed.
> I can either submit a follow-up or I can respin the original patch
> real quick so that it applies on top of the current ixgbe queue.

It was because Sridhar needed his patch applied before yours as a fix,
that was the issue.  Just send me the two line fix you have for the
patch and I will re-spin the patch with Sridhar's needed fix as well.
David Miller April 5, 2016, 1:27 a.m. UTC | #4
From: "Samudrala, Sridhar" <sridhar.samudrala@intel.com>
Date: Mon, 04 Apr 2016 15:32:37 -0700

> On 4/4/2016 3:14 PM, Jeff Kirsher wrote:
>> @@ -9190,41 +9148,37 @@ skip_sriov:
>>     #endif
>>   	netdev->features = NETIF_F_SG |
>> -			   NETIF_F_IP_CSUM |
>> -			   NETIF_F_IPV6_CSUM |
>> -			   NETIF_F_HW_VLAN_CTAG_TX |
>> -			   NETIF_F_HW_VLAN_CTAG_RX |
>>   			   NETIF_F_TSO |
>>   			   NETIF_F_TSO6 |
>>   			   NETIF_F_RXHASH |
>> -			   NETIF_F_RXCSUM;
>> -
>> -	netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
>> +			   NETIF_F_RXCSUM |
>> +			   NETIF_F_HW_CSUM |
>> +			   NETIF_F_SCTP_CRC |
>> +			   NETIF_F_HW_VLAN_CTAG_TX |
>> +			   NETIF_F_HW_VLAN_CTAG_RX;
>>   -	switch (adapter->hw.mac.type) {
>> -	case ixgbe_mac_82599EB:
>> -	case ixgbe_mac_X540:
>> -	case ixgbe_mac_X550:
>> -	case ixgbe_mac_X550EM_x:
>> +	if (hw->mac.type >= ixgbe_mac_82599EB)
>>   		netdev->features |= NETIF_F_SCTP_CRC;
>> -		netdev->hw_features |= NETIF_F_SCTP_CRC |
>> -				       NETIF_F_NTUPLE |
>> -				       NETIF_F_HW_TC;
>> -		break;
>> -	default:
>> -		break;
>> -	}
>>   -	netdev->hw_features |= NETIF_F_RXALL;
>> +	/* copy netdev features into list of user selectable features */
>> +	netdev->hw_features |= netdev->features;
>> +	netdev->hw_features |= NETIF_F_RXALL |
>> +			       NETIF_F_HW_L2FW_DOFFLOAD;
>> +
>> +	if (hw->mac.type >= ixgbe_mac_82599EB)
>> +		netdev->hw_features |= NETIF_F_NTUPLE;
> 
> looks like the cleanup missed moving NETIF_F_HW_TC flag here that
> enables cls_u32 offloads via TC.

Indeed, this is a regression.
Kirsher, Jeffrey T April 5, 2016, 1:29 a.m. UTC | #5
On Mon, 2016-04-04 at 21:27 -0400, David Miller wrote:
> From: "Samudrala, Sridhar" <sridhar.samudrala@intel.com>
> Date: Mon, 04 Apr 2016 15:32:37 -0700
> 
> > 
> > On 4/4/2016 3:14 PM, Jeff Kirsher wrote:
> > > 
> > > @@ -9190,41 +9148,37 @@ skip_sriov:
> > >     #endif
> > >   	netdev->features = NETIF_F_SG |
> > > -			   NETIF_F_IP_CSUM |
> > > -			   NETIF_F_IPV6_CSUM |
> > > -			   NETIF_F_HW_VLAN_CTAG_TX |
> > > -			   NETIF_F_HW_VLAN_CTAG_RX |
> > >   			   NETIF_F_TSO |
> > >   			   NETIF_F_TSO6 |
> > >   			   NETIF_F_RXHASH |
> > > -			   NETIF_F_RXCSUM;
> > > -
> > > -	netdev->hw_features = netdev->features |
> > > NETIF_F_HW_L2FW_DOFFLOAD;
> > > +			   NETIF_F_RXCSUM |
> > > +			   NETIF_F_HW_CSUM |
> > > +			   NETIF_F_SCTP_CRC |
> > > +			   NETIF_F_HW_VLAN_CTAG_TX |
> > > +			   NETIF_F_HW_VLAN_CTAG_RX;
> > >   -	switch (adapter->hw.mac.type) {
> > > -	case ixgbe_mac_82599EB:
> > > -	case ixgbe_mac_X540:
> > > -	case ixgbe_mac_X550:
> > > -	case ixgbe_mac_X550EM_x:
> > > +	if (hw->mac.type >= ixgbe_mac_82599EB)
> > >   		netdev->features |= NETIF_F_SCTP_CRC;
> > > -		netdev->hw_features |= NETIF_F_SCTP_CRC |
> > > -				       NETIF_F_NTUPLE |
> > > -				       NETIF_F_HW_TC;
> > > -		break;
> > > -	default:
> > > -		break;
> > > -	}
> > >   -	netdev->hw_features |= NETIF_F_RXALL;
> > > +	/* copy netdev features into list of user selectable
> > > features */
> > > +	netdev->hw_features |= netdev->features;
> > > +	netdev->hw_features |= NETIF_F_RXALL |
> > > +			       NETIF_F_HW_L2FW_DOFFLOAD;
> > > +
> > > +	if (hw->mac.type >= ixgbe_mac_82599EB)
> > > +		netdev->hw_features |= NETIF_F_NTUPLE;
> > looks like the cleanup missed moving NETIF_F_HW_TC flag here that
> > enables cls_u32 offloads via TC.
> Indeed, this is a regression.

I took care of it in v2.
diff mbox

Patch

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index bce5737..8d248c8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7202,103 +7202,61 @@  static int ixgbe_tso(struct ixgbe_ring *tx_ring,
 	return 1;
 }
 
+static inline bool ixgbe_ipv6_csum_is_sctp(struct sk_buff *skb)
+{
+	unsigned int offset = 0;
+
+	ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL);
+
+	return offset == skb_checksum_start_offset(skb);
+}
+
 static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
 			  struct ixgbe_tx_buffer *first)
 {
 	struct sk_buff *skb = first->skb;
 	u32 vlan_macip_lens = 0;
-	u32 mss_l4len_idx = 0;
 	u32 type_tucmd = 0;
 
 	if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		if (!(first->tx_flags & IXGBE_TX_FLAGS_HW_VLAN) &&
-		    !(first->tx_flags & IXGBE_TX_FLAGS_CC))
+csum_failed:
+		if (!(first->tx_flags & (IXGBE_TX_FLAGS_HW_VLAN |
+					 IXGBE_TX_FLAGS_CC)))
 			return;
-		vlan_macip_lens = skb_network_offset(skb) <<
-				  IXGBE_ADVTXD_MACLEN_SHIFT;
-	} else {
-		u8 l4_hdr = 0;
-		union {
-			struct iphdr *ipv4;
-			struct ipv6hdr *ipv6;
-			u8 *raw;
-		} network_hdr;
-		union {
-			struct tcphdr *tcphdr;
-			u8 *raw;
-		} transport_hdr;
-		__be16 frag_off;
-
-		if (skb->encapsulation) {
-			network_hdr.raw = skb_inner_network_header(skb);
-			transport_hdr.raw = skb_inner_transport_header(skb);
-			vlan_macip_lens = skb_inner_network_offset(skb) <<
-					  IXGBE_ADVTXD_MACLEN_SHIFT;
-		} else {
-			network_hdr.raw = skb_network_header(skb);
-			transport_hdr.raw = skb_transport_header(skb);
-			vlan_macip_lens = skb_network_offset(skb) <<
-					  IXGBE_ADVTXD_MACLEN_SHIFT;
-		}
+		goto no_csum;
+	}
 
-		/* use first 4 bits to determine IP version */
-		switch (network_hdr.ipv4->version) {
-		case IPVERSION:
-			vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
-			type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
-			l4_hdr = network_hdr.ipv4->protocol;
-			break;
-		case 6:
-			vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
-			l4_hdr = network_hdr.ipv6->nexthdr;
-			if (likely((transport_hdr.raw - network_hdr.raw) ==
-				   sizeof(struct ipv6hdr)))
-				break;
-			ipv6_skip_exthdr(skb, network_hdr.raw - skb->data +
-					      sizeof(struct ipv6hdr),
-					 &l4_hdr, &frag_off);
-			if (unlikely(frag_off))
-				l4_hdr = NEXTHDR_FRAGMENT;
-			break;
-		default:
+	switch (skb->csum_offset) {
+	case offsetof(struct tcphdr, check):
+		type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
+		/* fall through */
+	case offsetof(struct udphdr, check):
+		break;
+	case offsetof(struct sctphdr, checksum):
+		/* validate that this is actually an SCTP request */
+		if (((first->protocol == htons(ETH_P_IP)) &&
+		     (ip_hdr(skb)->protocol == IPPROTO_SCTP)) ||
+		    ((first->protocol == htons(ETH_P_IPV6)) &&
+		     ixgbe_ipv6_csum_is_sctp(skb))) {
+			type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP;
 			break;
 		}
-
-		switch (l4_hdr) {
-		case IPPROTO_TCP:
-			type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
-			mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
-					IXGBE_ADVTXD_L4LEN_SHIFT;
-			break;
-		case IPPROTO_SCTP:
-			type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
-			mss_l4len_idx = sizeof(struct sctphdr) <<
-					IXGBE_ADVTXD_L4LEN_SHIFT;
-			break;
-		case IPPROTO_UDP:
-			mss_l4len_idx = sizeof(struct udphdr) <<
-					IXGBE_ADVTXD_L4LEN_SHIFT;
-			break;
-		default:
-			if (unlikely(net_ratelimit())) {
-				dev_warn(tx_ring->dev,
-					 "partial checksum, version=%d, l4 proto=%x\n",
-					 network_hdr.ipv4->version, l4_hdr);
-			}
-			skb_checksum_help(skb);
-			goto no_csum;
-		}
-
-		/* update TX checksum flag */
-		first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
+		/* fall through */
+	default:
+		skb_checksum_help(skb);
+		goto csum_failed;
 	}
 
+	/* update TX checksum flag */
+	first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
+	vlan_macip_lens = skb_checksum_start_offset(skb) -
+			  skb_network_offset(skb);
 no_csum:
 	/* vlan_macip_lens: MACLEN, VLAN tag */
+	vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
 	vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
 
-	ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
-			  type_tucmd, mss_l4len_idx);
+	ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, 0);
 }
 
 #define IXGBE_SET_FLAG(_input, _flag, _result) \
@@ -9190,41 +9148,37 @@  skip_sriov:
 
 #endif
 	netdev->features = NETIF_F_SG |
-			   NETIF_F_IP_CSUM |
-			   NETIF_F_IPV6_CSUM |
-			   NETIF_F_HW_VLAN_CTAG_TX |
-			   NETIF_F_HW_VLAN_CTAG_RX |
 			   NETIF_F_TSO |
 			   NETIF_F_TSO6 |
 			   NETIF_F_RXHASH |
-			   NETIF_F_RXCSUM;
-
-	netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
+			   NETIF_F_RXCSUM |
+			   NETIF_F_HW_CSUM |
+			   NETIF_F_SCTP_CRC |
+			   NETIF_F_HW_VLAN_CTAG_TX |
+			   NETIF_F_HW_VLAN_CTAG_RX;
 
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-	case ixgbe_mac_X550:
-	case ixgbe_mac_X550EM_x:
+	if (hw->mac.type >= ixgbe_mac_82599EB)
 		netdev->features |= NETIF_F_SCTP_CRC;
-		netdev->hw_features |= NETIF_F_SCTP_CRC |
-				       NETIF_F_NTUPLE |
-				       NETIF_F_HW_TC;
-		break;
-	default:
-		break;
-	}
 
-	netdev->hw_features |= NETIF_F_RXALL;
+	/* copy netdev features into list of user selectable features */
+	netdev->hw_features |= netdev->features;
+	netdev->hw_features |= NETIF_F_RXALL |
+			       NETIF_F_HW_L2FW_DOFFLOAD;
+
+	if (hw->mac.type >= ixgbe_mac_82599EB)
+		netdev->hw_features |= NETIF_F_NTUPLE;
+
+	/* set this bit last since it cannot be part of hw_features */
 	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
-	netdev->vlan_features |= NETIF_F_TSO;
-	netdev->vlan_features |= NETIF_F_TSO6;
-	netdev->vlan_features |= NETIF_F_IP_CSUM;
-	netdev->vlan_features |= NETIF_F_IPV6_CSUM;
-	netdev->vlan_features |= NETIF_F_SG;
+	netdev->vlan_features |= NETIF_F_SG |
+				 NETIF_F_TSO |
+				 NETIF_F_TSO6 |
+				 NETIF_F_HW_CSUM |
+				 NETIF_F_SCTP_CRC;
 
-	netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev->mpls_features |= NETIF_F_HW_CSUM;
+	netdev->hw_enc_features |= NETIF_F_HW_CSUM;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->priv_flags |= IFF_SUPP_NOFCS;