Skip to content

Commit 49763de

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
ixgbe: Add support for generic Tx checksums
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 <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent c7374b5 commit 49763de

File tree

1 file changed

+58
-104
lines changed

1 file changed

+58
-104
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 58 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -7202,103 +7202,61 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
72027202
return 1;
72037203
}
72047204

7205+
static inline bool ixgbe_ipv6_csum_is_sctp(struct sk_buff *skb)
7206+
{
7207+
unsigned int offset = 0;
7208+
7209+
ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL);
7210+
7211+
return offset == skb_checksum_start_offset(skb);
7212+
}
7213+
72057214
static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
72067215
struct ixgbe_tx_buffer *first)
72077216
{
72087217
struct sk_buff *skb = first->skb;
72097218
u32 vlan_macip_lens = 0;
7210-
u32 mss_l4len_idx = 0;
72117219
u32 type_tucmd = 0;
72127220

72137221
if (skb->ip_summed != CHECKSUM_PARTIAL) {
7214-
if (!(first->tx_flags & IXGBE_TX_FLAGS_HW_VLAN) &&
7215-
!(first->tx_flags & IXGBE_TX_FLAGS_CC))
7222+
csum_failed:
7223+
if (!(first->tx_flags & (IXGBE_TX_FLAGS_HW_VLAN |
7224+
IXGBE_TX_FLAGS_CC)))
72167225
return;
7217-
vlan_macip_lens = skb_network_offset(skb) <<
7218-
IXGBE_ADVTXD_MACLEN_SHIFT;
7219-
} else {
7220-
u8 l4_hdr = 0;
7221-
union {
7222-
struct iphdr *ipv4;
7223-
struct ipv6hdr *ipv6;
7224-
u8 *raw;
7225-
} network_hdr;
7226-
union {
7227-
struct tcphdr *tcphdr;
7228-
u8 *raw;
7229-
} transport_hdr;
7230-
__be16 frag_off;
7231-
7232-
if (skb->encapsulation) {
7233-
network_hdr.raw = skb_inner_network_header(skb);
7234-
transport_hdr.raw = skb_inner_transport_header(skb);
7235-
vlan_macip_lens = skb_inner_network_offset(skb) <<
7236-
IXGBE_ADVTXD_MACLEN_SHIFT;
7237-
} else {
7238-
network_hdr.raw = skb_network_header(skb);
7239-
transport_hdr.raw = skb_transport_header(skb);
7240-
vlan_macip_lens = skb_network_offset(skb) <<
7241-
IXGBE_ADVTXD_MACLEN_SHIFT;
7242-
}
7226+
goto no_csum;
7227+
}
72437228

7244-
/* use first 4 bits to determine IP version */
7245-
switch (network_hdr.ipv4->version) {
7246-
case IPVERSION:
7247-
vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
7248-
type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
7249-
l4_hdr = network_hdr.ipv4->protocol;
7250-
break;
7251-
case 6:
7252-
vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
7253-
l4_hdr = network_hdr.ipv6->nexthdr;
7254-
if (likely((transport_hdr.raw - network_hdr.raw) ==
7255-
sizeof(struct ipv6hdr)))
7256-
break;
7257-
ipv6_skip_exthdr(skb, network_hdr.raw - skb->data +
7258-
sizeof(struct ipv6hdr),
7259-
&l4_hdr, &frag_off);
7260-
if (unlikely(frag_off))
7261-
l4_hdr = NEXTHDR_FRAGMENT;
7262-
break;
7263-
default:
7229+
switch (skb->csum_offset) {
7230+
case offsetof(struct tcphdr, check):
7231+
type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
7232+
/* fall through */
7233+
case offsetof(struct udphdr, check):
7234+
break;
7235+
case offsetof(struct sctphdr, checksum):
7236+
/* validate that this is actually an SCTP request */
7237+
if (((first->protocol == htons(ETH_P_IP)) &&
7238+
(ip_hdr(skb)->protocol == IPPROTO_SCTP)) ||
7239+
((first->protocol == htons(ETH_P_IPV6)) &&
7240+
ixgbe_ipv6_csum_is_sctp(skb))) {
7241+
type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP;
72647242
break;
72657243
}
7266-
7267-
switch (l4_hdr) {
7268-
case IPPROTO_TCP:
7269-
type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
7270-
mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
7271-
IXGBE_ADVTXD_L4LEN_SHIFT;
7272-
break;
7273-
case IPPROTO_SCTP:
7274-
type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
7275-
mss_l4len_idx = sizeof(struct sctphdr) <<
7276-
IXGBE_ADVTXD_L4LEN_SHIFT;
7277-
break;
7278-
case IPPROTO_UDP:
7279-
mss_l4len_idx = sizeof(struct udphdr) <<
7280-
IXGBE_ADVTXD_L4LEN_SHIFT;
7281-
break;
7282-
default:
7283-
if (unlikely(net_ratelimit())) {
7284-
dev_warn(tx_ring->dev,
7285-
"partial checksum, version=%d, l4 proto=%x\n",
7286-
network_hdr.ipv4->version, l4_hdr);
7287-
}
7288-
skb_checksum_help(skb);
7289-
goto no_csum;
7290-
}
7291-
7292-
/* update TX checksum flag */
7293-
first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
7244+
/* fall through */
7245+
default:
7246+
skb_checksum_help(skb);
7247+
goto csum_failed;
72947248
}
72957249

7250+
/* update TX checksum flag */
7251+
first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
7252+
vlan_macip_lens = skb_checksum_start_offset(skb) -
7253+
skb_network_offset(skb);
72967254
no_csum:
72977255
/* vlan_macip_lens: MACLEN, VLAN tag */
7256+
vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
72987257
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
72997258

7300-
ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
7301-
type_tucmd, mss_l4len_idx);
7259+
ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, 0);
73027260
}
73037261

73047262
#define IXGBE_SET_FLAG(_input, _flag, _result) \
@@ -9190,41 +9148,37 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
91909148

91919149
#endif
91929150
netdev->features = NETIF_F_SG |
9193-
NETIF_F_IP_CSUM |
9194-
NETIF_F_IPV6_CSUM |
9195-
NETIF_F_HW_VLAN_CTAG_TX |
9196-
NETIF_F_HW_VLAN_CTAG_RX |
91979151
NETIF_F_TSO |
91989152
NETIF_F_TSO6 |
91999153
NETIF_F_RXHASH |
9200-
NETIF_F_RXCSUM;
9201-
9202-
netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
9154+
NETIF_F_RXCSUM |
9155+
NETIF_F_HW_CSUM |
9156+
NETIF_F_HW_VLAN_CTAG_TX |
9157+
NETIF_F_HW_VLAN_CTAG_RX;
92039158

9204-
switch (adapter->hw.mac.type) {
9205-
case ixgbe_mac_82599EB:
9206-
case ixgbe_mac_X540:
9207-
case ixgbe_mac_X550:
9208-
case ixgbe_mac_X550EM_x:
9159+
if (hw->mac.type >= ixgbe_mac_82599EB)
92099160
netdev->features |= NETIF_F_SCTP_CRC;
9210-
netdev->hw_features |= NETIF_F_SCTP_CRC |
9211-
NETIF_F_NTUPLE |
9161+
9162+
/* copy netdev features into list of user selectable features */
9163+
netdev->hw_features |= netdev->features;
9164+
netdev->hw_features |= NETIF_F_RXALL |
9165+
NETIF_F_HW_L2FW_DOFFLOAD;
9166+
9167+
if (hw->mac.type >= ixgbe_mac_82599EB)
9168+
netdev->hw_features |= NETIF_F_NTUPLE |
92129169
NETIF_F_HW_TC;
9213-
break;
9214-
default:
9215-
break;
9216-
}
92179170

9218-
netdev->hw_features |= NETIF_F_RXALL;
9171+
/* set this bit last since it cannot be part of hw_features */
92199172
netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
92209173

9221-
netdev->vlan_features |= NETIF_F_TSO;
9222-
netdev->vlan_features |= NETIF_F_TSO6;
9223-
netdev->vlan_features |= NETIF_F_IP_CSUM;
9224-
netdev->vlan_features |= NETIF_F_IPV6_CSUM;
9225-
netdev->vlan_features |= NETIF_F_SG;
9174+
netdev->vlan_features |= NETIF_F_SG |
9175+
NETIF_F_TSO |
9176+
NETIF_F_TSO6 |
9177+
NETIF_F_HW_CSUM |
9178+
NETIF_F_SCTP_CRC;
92269179

9227-
netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
9180+
netdev->mpls_features |= NETIF_F_HW_CSUM;
9181+
netdev->hw_enc_features |= NETIF_F_HW_CSUM;
92289182

92299183
netdev->priv_flags |= IFF_UNICAST_FLT;
92309184
netdev->priv_flags |= IFF_SUPP_NOFCS;

0 commit comments

Comments
 (0)