mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 14:43:58 +08:00
i40e: Rx checksum offload for VXLAN
This implements receive offload for VXLAN for i40e. The hardware supports checksum offload/verification of the inner/outer header. Change-Id: I450db300af6713f2044fef1191a0d1d294c13369 Signed-off-by: Joseph Gasparakis <joseph.gasparakis@intel.com> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
a1c9a9d998
commit
8144f0f7e9
@ -29,6 +29,7 @@
|
||||
#define _I40E_H_
|
||||
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
|
@ -860,12 +860,25 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
|
||||
* @skb: skb currently being received and modified
|
||||
* @rx_status: status value of last descriptor in packet
|
||||
* @rx_error: error value of last descriptor in packet
|
||||
* @rx_ptype: ptype value of last descriptor in packet
|
||||
**/
|
||||
static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
|
||||
struct sk_buff *skb,
|
||||
u32 rx_status,
|
||||
u32 rx_error)
|
||||
u32 rx_error,
|
||||
u16 rx_ptype)
|
||||
{
|
||||
bool ipv4_tunnel, ipv6_tunnel;
|
||||
__wsum rx_udp_csum;
|
||||
__sum16 csum;
|
||||
struct iphdr *iph;
|
||||
|
||||
ipv4_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT4_MAC_PAY3) &&
|
||||
(rx_ptype < I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4);
|
||||
ipv6_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT6_MAC_PAY3) &&
|
||||
(rx_ptype < I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4);
|
||||
|
||||
skb->encapsulation = ipv4_tunnel || ipv6_tunnel;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
/* Rx csum enabled and ip headers found? */
|
||||
@ -873,13 +886,43 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
|
||||
rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
|
||||
return;
|
||||
|
||||
/* IP or L4 checksum error */
|
||||
/* IP or L4 or outmost IP checksum error */
|
||||
if (rx_error & ((1 << I40E_RX_DESC_ERROR_IPE_SHIFT) |
|
||||
(1 << I40E_RX_DESC_ERROR_L4E_SHIFT))) {
|
||||
(1 << I40E_RX_DESC_ERROR_L4E_SHIFT) |
|
||||
(1 << I40E_RX_DESC_ERROR_EIPE_SHIFT))) {
|
||||
vsi->back->hw_csum_rx_error++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipv4_tunnel &&
|
||||
!(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) {
|
||||
/* If VXLAN traffic has an outer UDPv4 checksum we need to check
|
||||
* it in the driver, hardware does not do it for us.
|
||||
* Since L3L4P bit was set we assume a valid IHL value (>=5)
|
||||
* so the total length of IPv4 header is IHL*4 bytes
|
||||
*/
|
||||
skb->transport_header = skb->mac_header +
|
||||
sizeof(struct ethhdr) +
|
||||
(ip_hdr(skb)->ihl * 4);
|
||||
|
||||
/* Add 4 bytes for VLAN tagged packets */
|
||||
skb->transport_header += (skb->protocol == htons(ETH_P_8021Q) ||
|
||||
skb->protocol == htons(ETH_P_8021AD))
|
||||
? VLAN_HLEN : 0;
|
||||
|
||||
rx_udp_csum = udp_csum(skb);
|
||||
iph = ip_hdr(skb);
|
||||
csum = csum_tcpudp_magic(
|
||||
iph->saddr, iph->daddr,
|
||||
(skb->len - skb_transport_offset(skb)),
|
||||
IPPROTO_UDP, rx_udp_csum);
|
||||
|
||||
if (udp_hdr(skb)->check != csum) {
|
||||
vsi->back->hw_csum_rx_error++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
@ -920,6 +963,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
|
||||
union i40e_rx_desc *rx_desc;
|
||||
u32 rx_error, rx_status;
|
||||
u64 qword;
|
||||
u16 rx_ptype;
|
||||
|
||||
rx_desc = I40E_RX_DESC(rx_ring, i);
|
||||
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
|
||||
@ -952,6 +996,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
|
||||
rx_hbo = rx_error & (1 << I40E_RX_DESC_ERROR_HBO_SHIFT);
|
||||
rx_error &= ~(1 << I40E_RX_DESC_ERROR_HBO_SHIFT);
|
||||
|
||||
rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
|
||||
I40E_RXD_QW1_PTYPE_SHIFT;
|
||||
rx_bi->skb = NULL;
|
||||
|
||||
/* This memory barrier is needed to keep us from reading
|
||||
@ -1032,13 +1078,14 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
|
||||
}
|
||||
|
||||
skb->rxhash = i40e_rx_hash(rx_ring, rx_desc);
|
||||
i40e_rx_checksum(vsi, skb, rx_status, rx_error);
|
||||
|
||||
/* probably a little skewed due to removing CRC */
|
||||
total_rx_bytes += skb->len;
|
||||
total_rx_packets++;
|
||||
|
||||
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
|
||||
|
||||
i40e_rx_checksum(vsi, skb, rx_status, rx_error, rx_ptype);
|
||||
|
||||
vlan_tag = rx_status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)
|
||||
? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1)
|
||||
: 0;
|
||||
|
@ -513,7 +513,8 @@ enum i40e_rx_desc_status_bits {
|
||||
I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */
|
||||
I40E_RX_DESC_STATUS_FLM_SHIFT = 11,
|
||||
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_UDP_0_SHIFT = 16
|
||||
};
|
||||
|
||||
#define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT I40E_RX_DESC_STATUS_TSYNINDX_SHIFT
|
||||
@ -559,28 +560,32 @@ enum i40e_rx_desc_error_l3l4e_fcoe_masks {
|
||||
|
||||
/* Packet type non-ip values */
|
||||
enum i40e_rx_l2_ptype {
|
||||
I40E_RX_PTYPE_L2_RESERVED = 0,
|
||||
I40E_RX_PTYPE_L2_MAC_PAY2 = 1,
|
||||
I40E_RX_PTYPE_L2_TIMESYNC_PAY2 = 2,
|
||||
I40E_RX_PTYPE_L2_FIP_PAY2 = 3,
|
||||
I40E_RX_PTYPE_L2_OUI_PAY2 = 4,
|
||||
I40E_RX_PTYPE_L2_MACCNTRL_PAY2 = 5,
|
||||
I40E_RX_PTYPE_L2_LLDP_PAY2 = 6,
|
||||
I40E_RX_PTYPE_L2_ECP_PAY2 = 7,
|
||||
I40E_RX_PTYPE_L2_EVB_PAY2 = 8,
|
||||
I40E_RX_PTYPE_L2_QCN_PAY2 = 9,
|
||||
I40E_RX_PTYPE_L2_EAPOL_PAY2 = 10,
|
||||
I40E_RX_PTYPE_L2_ARP = 11,
|
||||
I40E_RX_PTYPE_L2_FCOE_PAY3 = 12,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21
|
||||
I40E_RX_PTYPE_L2_RESERVED = 0,
|
||||
I40E_RX_PTYPE_L2_MAC_PAY2 = 1,
|
||||
I40E_RX_PTYPE_L2_TIMESYNC_PAY2 = 2,
|
||||
I40E_RX_PTYPE_L2_FIP_PAY2 = 3,
|
||||
I40E_RX_PTYPE_L2_OUI_PAY2 = 4,
|
||||
I40E_RX_PTYPE_L2_MACCNTRL_PAY2 = 5,
|
||||
I40E_RX_PTYPE_L2_LLDP_PAY2 = 6,
|
||||
I40E_RX_PTYPE_L2_ECP_PAY2 = 7,
|
||||
I40E_RX_PTYPE_L2_EVB_PAY2 = 8,
|
||||
I40E_RX_PTYPE_L2_QCN_PAY2 = 9,
|
||||
I40E_RX_PTYPE_L2_EAPOL_PAY2 = 10,
|
||||
I40E_RX_PTYPE_L2_ARP = 11,
|
||||
I40E_RX_PTYPE_L2_FCOE_PAY3 = 12,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15,
|
||||
I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20,
|
||||
I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21,
|
||||
I40E_RX_PTYPE_GRENAT4_MAC_PAY3 = 58,
|
||||
I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87,
|
||||
I40E_RX_PTYPE_GRENAT6_MAC_PAY3 = 124,
|
||||
I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153
|
||||
};
|
||||
|
||||
struct i40e_rx_ptype_decoded {
|
||||
|
Loading…
Reference in New Issue
Block a user