Commit 527274c7 authored by Anjali Singhai Jain's avatar Anjali Singhai Jain Committed by Jeff Kirsher

i40e/i40evf: Add TX/RX outer UDP checksum support for X722

X722 supports offloading of outer UDP TX and RX checksum for tunneled
packets. This patch exposes the support and leaves it enabled by
default.
Signed-off-by: default avatarAnjali Singhai Jain <anjali.singhai@intel.com>
Signed-off-by: default avatarCatherine Sullivan <catherine.sullivan@intel.com>
Tested-by: default avatarJim Young <james.m.young@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 8e0764b4
...@@ -7073,6 +7073,8 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi) ...@@ -7073,6 +7073,8 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
tx_ring->dcb_tc = 0; tx_ring->dcb_tc = 0;
if (vsi->back->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) if (vsi->back->flags & I40E_FLAG_WB_ON_ITR_CAPABLE)
tx_ring->flags = I40E_TXR_FLAGS_WB_ON_ITR; tx_ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
if (vsi->back->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE)
tx_ring->flags |= I40E_TXR_FLAGS_OUTER_UDP_CSUM;
vsi->tx_rings[i] = tx_ring; vsi->tx_rings[i] = tx_ring;
rx_ring = &tx_ring[1]; rx_ring = &tx_ring[1];
......
...@@ -1429,7 +1429,8 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, ...@@ -1429,7 +1429,8 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
* so the total length of IPv4 header is IHL*4 bytes * so the total length of IPv4 header is IHL*4 bytes
* The UDP_0 bit *may* bet set if the *inner* header is UDP * The UDP_0 bit *may* bet set if the *inner* header is UDP
*/ */
if (ipv4_tunnel) { if (!(vsi->back->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE) &&
(ipv4_tunnel)) {
skb->transport_header = skb->mac_header + skb->transport_header = skb->mac_header +
sizeof(struct ethhdr) + sizeof(struct ethhdr) +
(ip_hdr(skb)->ihl * 4); (ip_hdr(skb)->ihl * 4);
...@@ -2301,11 +2302,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2301,11 +2302,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
struct iphdr *this_ip_hdr; struct iphdr *this_ip_hdr;
u32 network_hdr_len; u32 network_hdr_len;
u8 l4_hdr = 0; u8 l4_hdr = 0;
struct udphdr *oudph;
struct iphdr *oiph;
u32 l4_tunnel = 0; u32 l4_tunnel = 0;
if (skb->encapsulation) { if (skb->encapsulation) {
switch (ip_hdr(skb)->protocol) { switch (ip_hdr(skb)->protocol) {
case IPPROTO_UDP: case IPPROTO_UDP:
oudph = udp_hdr(skb);
oiph = ip_hdr(skb);
l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING; l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break; break;
...@@ -2342,6 +2347,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -2342,6 +2347,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
*tx_flags &= ~I40E_TX_FLAGS_IPV4; *tx_flags &= ~I40E_TX_FLAGS_IPV4;
*tx_flags |= I40E_TX_FLAGS_IPV6; *tx_flags |= I40E_TX_FLAGS_IPV6;
} }
if ((tx_ring->flags & I40E_TXR_FLAGS_OUTER_UDP_CSUM) &&
(l4_tunnel == I40E_TXD_CTX_UDP_TUNNELING) &&
(*cd_tunneling & I40E_TXD_CTX_QW0_EXT_IP_MASK)) {
oudph->check = ~csum_tcpudp_magic(oiph->saddr,
oiph->daddr,
(skb->len - skb_transport_offset(skb)),
IPPROTO_UDP, 0);
*cd_tunneling |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
}
} else { } else {
network_hdr_len = skb_network_header_len(skb); network_hdr_len = skb_network_header_len(skb);
this_ip_hdr = ip_hdr(skb); this_ip_hdr = ip_hdr(skb);
......
...@@ -267,6 +267,8 @@ struct i40e_ring { ...@@ -267,6 +267,8 @@ struct i40e_ring {
u16 flags; u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
#define I40E_TXR_FLAGS_OUTER_UDP_CSUM BIT(1)
/* stats structs */ /* stats structs */
struct i40e_queue_stats stats; struct i40e_queue_stats stats;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
......
...@@ -607,14 +607,18 @@ enum i40e_rx_desc_status_bits { ...@@ -607,14 +607,18 @@ enum i40e_rx_desc_status_bits {
I40E_RX_DESC_STATUS_CRCP_SHIFT = 4, I40E_RX_DESC_STATUS_CRCP_SHIFT = 4,
I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */ I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */
I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7, I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7,
I40E_RX_DESC_STATUS_PIF_SHIFT = 8, /* Note: Bit 8 is reserved in X710 and XL710 */
I40E_RX_DESC_STATUS_EXT_UDP_0_SHIFT = 8,
I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */ I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */
I40E_RX_DESC_STATUS_FLM_SHIFT = 11, I40E_RX_DESC_STATUS_FLM_SHIFT = 11,
I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */ I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */
I40E_RX_DESC_STATUS_LPBK_SHIFT = 14, I40E_RX_DESC_STATUS_LPBK_SHIFT = 14,
I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15, I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15,
I40E_RX_DESC_STATUS_RESERVED_SHIFT = 16, /* 2 BITS */ I40E_RX_DESC_STATUS_RESERVED_SHIFT = 16, /* 2 BITS */
I40E_RX_DESC_STATUS_UDP_0_SHIFT = 18, /* Note: For non-tunnel packets INT_UDP_0 is the right status for
* UDP header
*/
I40E_RX_DESC_STATUS_INT_UDP_0_SHIFT = 18,
I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */ I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */
}; };
...@@ -955,6 +959,8 @@ enum i40e_tx_ctx_desc_eipt_offload { ...@@ -955,6 +959,8 @@ enum i40e_tx_ctx_desc_eipt_offload {
#define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \ #define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \
I40E_TXD_CTX_QW0_DECTTL_SHIFT) I40E_TXD_CTX_QW0_DECTTL_SHIFT)
#define I40E_TXD_CTX_QW0_L4T_CS_SHIFT 23
#define I40E_TXD_CTX_QW0_L4T_CS_MASK BIT_ULL(I40E_TXD_CTX_QW0_L4T_CS_SHIFT)
struct i40e_filter_program_desc { struct i40e_filter_program_desc {
__le32 qindex_flex_ptype_vsi; __le32 qindex_flex_ptype_vsi;
__le32 rsvd; __le32 rsvd;
......
...@@ -1528,11 +1528,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1528,11 +1528,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
struct iphdr *this_ip_hdr; struct iphdr *this_ip_hdr;
u32 network_hdr_len; u32 network_hdr_len;
u8 l4_hdr = 0; u8 l4_hdr = 0;
struct udphdr *oudph;
struct iphdr *oiph;
u32 l4_tunnel = 0; u32 l4_tunnel = 0;
if (skb->encapsulation) { if (skb->encapsulation) {
switch (ip_hdr(skb)->protocol) { switch (ip_hdr(skb)->protocol) {
case IPPROTO_UDP: case IPPROTO_UDP:
oudph = udp_hdr(skb);
oiph = ip_hdr(skb);
l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING; l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING;
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break; break;
...@@ -1571,6 +1575,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, ...@@ -1571,6 +1575,15 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
} }
if ((tx_ring->flags & I40E_TXR_FLAGS_OUTER_UDP_CSUM) &&
(l4_tunnel == I40E_TXD_CTX_UDP_TUNNELING) &&
(*cd_tunneling & I40E_TXD_CTX_QW0_EXT_IP_MASK)) {
oudph->check = ~csum_tcpudp_magic(oiph->saddr,
oiph->daddr,
(skb->len - skb_transport_offset(skb)),
IPPROTO_UDP, 0);
*cd_tunneling |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
}
} else { } else {
network_hdr_len = skb_network_header_len(skb); network_hdr_len = skb_network_header_len(skb);
this_ip_hdr = ip_hdr(skb); this_ip_hdr = ip_hdr(skb);
......
...@@ -264,6 +264,8 @@ struct i40e_ring { ...@@ -264,6 +264,8 @@ struct i40e_ring {
u16 flags; u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
#define I40E_TXR_FLAGS_OUTER_UDP_CSUM BIT(1)
/* stats structs */ /* stats structs */
struct i40e_queue_stats stats; struct i40e_queue_stats stats;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
......
...@@ -601,14 +601,18 @@ enum i40e_rx_desc_status_bits { ...@@ -601,14 +601,18 @@ enum i40e_rx_desc_status_bits {
I40E_RX_DESC_STATUS_CRCP_SHIFT = 4, I40E_RX_DESC_STATUS_CRCP_SHIFT = 4,
I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */ I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */
I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7, I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7,
I40E_RX_DESC_STATUS_PIF_SHIFT = 8, /* Note: Bit 8 is reserved in X710 and XL710 */
I40E_RX_DESC_STATUS_EXT_UDP_0_SHIFT = 8,
I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */ I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */
I40E_RX_DESC_STATUS_FLM_SHIFT = 11, I40E_RX_DESC_STATUS_FLM_SHIFT = 11,
I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */ I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */
I40E_RX_DESC_STATUS_LPBK_SHIFT = 14, I40E_RX_DESC_STATUS_LPBK_SHIFT = 14,
I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15, I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15,
I40E_RX_DESC_STATUS_RESERVED_SHIFT = 16, /* 2 BITS */ I40E_RX_DESC_STATUS_RESERVED_SHIFT = 16, /* 2 BITS */
I40E_RX_DESC_STATUS_UDP_0_SHIFT = 18, /* Note: For non-tunnel packets INT_UDP_0 is the right status for
* UDP header
*/
I40E_RX_DESC_STATUS_INT_UDP_0_SHIFT = 18,
I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */ I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */
}; };
...@@ -949,6 +953,8 @@ enum i40e_tx_ctx_desc_eipt_offload { ...@@ -949,6 +953,8 @@ enum i40e_tx_ctx_desc_eipt_offload {
#define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \ #define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \
I40E_TXD_CTX_QW0_DECTTL_SHIFT) I40E_TXD_CTX_QW0_DECTTL_SHIFT)
#define I40E_TXD_CTX_QW0_L4T_CS_SHIFT 23
#define I40E_TXD_CTX_QW0_L4T_CS_MASK BIT_ULL(I40E_TXD_CTX_QW0_L4T_CS_SHIFT)
struct i40e_filter_program_desc { struct i40e_filter_program_desc {
__le32 qindex_flex_ptype_vsi; __le32 qindex_flex_ptype_vsi;
__le32 rsvd; __le32 rsvd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment