Skip to content

Commit cb2b3ed

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
ixgbevf: Add support for generic Tx checksums
This patch adds support for generic Tx checksums to the ixgbevf 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. In the case of the VF drivers this meant adding support for SCTP CRCs, and inner checksum offloads for MPLS and various tunnel types. Signed-off-by: Alexander Duyck <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 49763de commit cb2b3ed

File tree

1 file changed

+43
-61
lines changed

1 file changed

+43
-61
lines changed

drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

Lines changed: 43 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3334,76 +3334,55 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
33343334
return 1;
33353335
}
33363336

3337+
static inline bool ixgbevf_ipv6_csum_is_sctp(struct sk_buff *skb)
3338+
{
3339+
unsigned int offset = 0;
3340+
3341+
ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL);
3342+
3343+
return offset == skb_checksum_start_offset(skb);
3344+
}
3345+
33373346
static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
33383347
struct ixgbevf_tx_buffer *first)
33393348
{
33403349
struct sk_buff *skb = first->skb;
33413350
u32 vlan_macip_lens = 0;
3342-
u32 mss_l4len_idx = 0;
33433351
u32 type_tucmd = 0;
33443352

3345-
if (skb->ip_summed == CHECKSUM_PARTIAL) {
3346-
u8 l4_hdr = 0;
3347-
__be16 frag_off;
3348-
3349-
switch (first->protocol) {
3350-
case htons(ETH_P_IP):
3351-
vlan_macip_lens |= skb_network_header_len(skb);
3352-
type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
3353-
l4_hdr = ip_hdr(skb)->protocol;
3354-
break;
3355-
case htons(ETH_P_IPV6):
3356-
vlan_macip_lens |= skb_network_header_len(skb);
3357-
l4_hdr = ipv6_hdr(skb)->nexthdr;
3358-
if (likely(skb_network_header_len(skb) ==
3359-
sizeof(struct ipv6hdr)))
3360-
break;
3361-
ipv6_skip_exthdr(skb, skb_network_offset(skb) +
3362-
sizeof(struct ipv6hdr),
3363-
&l4_hdr, &frag_off);
3364-
if (unlikely(frag_off))
3365-
l4_hdr = NEXTHDR_FRAGMENT;
3366-
break;
3367-
default:
3368-
break;
3369-
}
3353+
if (skb->ip_summed != CHECKSUM_PARTIAL)
3354+
goto no_csum;
33703355

3371-
switch (l4_hdr) {
3372-
case IPPROTO_TCP:
3373-
type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
3374-
mss_l4len_idx = tcp_hdrlen(skb) <<
3375-
IXGBE_ADVTXD_L4LEN_SHIFT;
3376-
break;
3377-
case IPPROTO_SCTP:
3378-
type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
3379-
mss_l4len_idx = sizeof(struct sctphdr) <<
3380-
IXGBE_ADVTXD_L4LEN_SHIFT;
3381-
break;
3382-
case IPPROTO_UDP:
3383-
mss_l4len_idx = sizeof(struct udphdr) <<
3384-
IXGBE_ADVTXD_L4LEN_SHIFT;
3356+
switch (skb->csum_offset) {
3357+
case offsetof(struct tcphdr, check):
3358+
type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
3359+
/* fall through */
3360+
case offsetof(struct udphdr, check):
3361+
break;
3362+
case offsetof(struct sctphdr, checksum):
3363+
/* validate that this is actually an SCTP request */
3364+
if (((first->protocol == htons(ETH_P_IP)) &&
3365+
(ip_hdr(skb)->protocol == IPPROTO_SCTP)) ||
3366+
((first->protocol == htons(ETH_P_IPV6)) &&
3367+
ixgbevf_ipv6_csum_is_sctp(skb))) {
3368+
type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP;
33853369
break;
3386-
default:
3387-
if (unlikely(net_ratelimit())) {
3388-
dev_warn(tx_ring->dev,
3389-
"partial checksum, l3 proto=%x, l4 proto=%x\n",
3390-
first->protocol, l4_hdr);
3391-
}
3392-
skb_checksum_help(skb);
3393-
goto no_csum;
33943370
}
3395-
3396-
/* update TX checksum flag */
3397-
first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
3371+
/* fall through */
3372+
default:
3373+
skb_checksum_help(skb);
3374+
goto no_csum;
33983375
}
3399-
3376+
/* update TX checksum flag */
3377+
first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
3378+
vlan_macip_lens = skb_checksum_start_offset(skb) -
3379+
skb_network_offset(skb);
34003380
no_csum:
34013381
/* vlan_macip_lens: MACLEN, VLAN tag */
34023382
vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
34033383
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
34043384

3405-
ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens,
3406-
type_tucmd, mss_l4len_idx);
3385+
ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, 0);
34073386
}
34083387

34093388
static __le32 ixgbevf_tx_cmd_type(u32 tx_flags)
@@ -4010,22 +3989,25 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
40103989
}
40113990

40123991
netdev->hw_features = NETIF_F_SG |
4013-
NETIF_F_IP_CSUM |
4014-
NETIF_F_IPV6_CSUM |
40153992
NETIF_F_TSO |
40163993
NETIF_F_TSO6 |
4017-
NETIF_F_RXCSUM;
3994+
NETIF_F_RXCSUM |
3995+
NETIF_F_HW_CSUM |
3996+
NETIF_F_SCTP_CRC;
40183997

40193998
netdev->features = netdev->hw_features |
40203999
NETIF_F_HW_VLAN_CTAG_TX |
40214000
NETIF_F_HW_VLAN_CTAG_RX |
40224001
NETIF_F_HW_VLAN_CTAG_FILTER;
40234002

4024-
netdev->vlan_features |= NETIF_F_TSO |
4003+
netdev->vlan_features |= NETIF_F_SG |
4004+
NETIF_F_TSO |
40254005
NETIF_F_TSO6 |
4026-
NETIF_F_IP_CSUM |
4027-
NETIF_F_IPV6_CSUM |
4028-
NETIF_F_SG;
4006+
NETIF_F_HW_CSUM |
4007+
NETIF_F_SCTP_CRC;
4008+
4009+
netdev->mpls_features |= NETIF_F_HW_CSUM;
4010+
netdev->hw_enc_features |= NETIF_F_HW_CSUM;
40294011

40304012
if (pci_using_dac)
40314013
netdev->features |= NETIF_F_HIGHDMA;

0 commit comments

Comments
 (0)