Commit 306ec721 authored by Alexander Lobakin's avatar Alexander Lobakin Committed by Tony Nguyen

net: intel: introduce {, Intel} Ethernet common library

Not a secret there's a ton of code duplication between two and more Intel
ethernet modules.

Before introducing new changes, which would need to be copied over again,
start decoupling the already existing duplicate functionality into a new
module, which will be shared between several Intel Ethernet drivers.
Add the lookup table which converts 8/10-bit hardware packet type into
a parsed bitfield structure for easy checking packet format parameters,
such as payload level, IP version, etc. This is currently used by i40e,
ice and iavf and it's all the same in all three drivers.
The only difference introduced in this implementation is that instead of
defining a 256 (or 1024 in case of ice) element array, add unlikely()
condition to limit the input to 154 (current maximum non-reserved packet
type). There's no reason to waste 600 (or even 3600) bytes only to not
hurt very unlikely exception packets.
The hash computation function now takes payload level directly as a
pkt_hash_type. There's a couple cases when non-IP ptypes are marked as
L3 payload and in the previous versions their hash level would be 2, not
3. But skb_set_hash() only sees difference between L4 and non-L4, thus
this won't change anything at all.
The module is behind the hidden Kconfig symbol, which the drivers will
select when needed. The exports are behind 'LIBIE' namespace to limit
the scope of the functions.

Not that non-HW-specific symbols will live in yet another module,
libeth. This is done to easily distinguish pretty generic code ready
for reusing by any other vendor and/or for moving the layer up from
the code useful in Intel's 1-100G drivers only.
Signed-off-by: default avatarAlexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 9dd15d50
......@@ -16,6 +16,9 @@ config NET_VENDOR_INTEL
if NET_VENDOR_INTEL
source "drivers/net/ethernet/intel/libeth/Kconfig"
source "drivers/net/ethernet/intel/libie/Kconfig"
config E100
tristate "Intel(R) PRO/100+ support"
depends on PCI
......@@ -225,6 +228,7 @@ config I40E
depends on PTP_1588_CLOCK_OPTIONAL
depends on PCI
select AUXILIARY_BUS
select LIBIE
select NET_DEVLINK
help
This driver supports Intel(R) Ethernet Controller XL710 Family of
......@@ -253,6 +257,8 @@ config I40E_DCB
# so that CONFIG_IAVF symbol will always mirror the state of CONFIG_I40EVF
config IAVF
tristate
select LIBIE
config I40EVF
tristate "Intel(R) Ethernet Adaptive Virtual Function support"
select IAVF
......@@ -283,6 +289,7 @@ config ICE
depends on GNSS || GNSS = n
select AUXILIARY_BUS
select DIMLIB
select LIBIE
select NET_DEVLINK
select PLDMFW
select DPLL
......
......@@ -3,6 +3,9 @@
# Makefile for the Intel network device drivers.
#
obj-$(CONFIG_LIBETH) += libeth/
obj-$(CONFIG_LIBIE) += libie/
obj-$(CONFIG_E100) += e100.o
obj-$(CONFIG_E1000) += e1000/
obj-$(CONFIG_E1000E) += e1000e/
......
......@@ -100,6 +100,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX
MODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver");
MODULE_IMPORT_NS(LIBIE);
MODULE_LICENSE("GPL v2");
static struct workqueue_struct *i40e_wq;
......
......@@ -371,13 +371,6 @@ void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
int i40e_set_mac_type(struct i40e_hw *hw);
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
{
return i40e_ptype_lookup[ptype];
}
/**
* i40e_virtchnl_link_speed - Convert AdminQ link_speed to virtchnl definition
* @link_speed: the speed to convert
......
......@@ -2,6 +2,7 @@
/* Copyright(c) 2013 - 2018 Intel Corporation. */
#include <linux/bpf_trace.h>
#include <linux/net/intel/libie/rx.h>
#include <linux/prefetch.h>
#include <linux/sctp.h>
#include <net/mpls.h>
......@@ -1741,38 +1742,30 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
struct sk_buff *skb,
union i40e_rx_desc *rx_desc)
{
struct i40e_rx_ptype_decoded decoded;
struct libeth_rx_pt decoded;
u32 rx_error, rx_status;
bool ipv4, ipv6;
u8 ptype;
u64 qword;
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
ptype = FIELD_GET(I40E_RXD_QW1_PTYPE_MASK, qword);
rx_error = FIELD_GET(I40E_RXD_QW1_ERROR_MASK, qword);
rx_status = FIELD_GET(I40E_RXD_QW1_STATUS_MASK, qword);
decoded = decode_rx_desc_ptype(ptype);
skb->ip_summed = CHECKSUM_NONE;
skb_checksum_none_assert(skb);
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
ptype = FIELD_GET(I40E_RXD_QW1_PTYPE_MASK, qword);
/* Rx csum enabled and ip headers found? */
if (!(vsi->netdev->features & NETIF_F_RXCSUM))
decoded = libie_rx_pt_parse(ptype);
if (!libeth_rx_pt_has_checksum(vsi->netdev, decoded))
return;
rx_error = FIELD_GET(I40E_RXD_QW1_ERROR_MASK, qword);
rx_status = FIELD_GET(I40E_RXD_QW1_STATUS_MASK, qword);
/* did the hardware decode the packet and checksum? */
if (!(rx_status & BIT(I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
return;
/* both known and outer_ip must be set for the below code to work */
if (!(decoded.known && decoded.outer_ip))
return;
ipv4 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
(decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4);
ipv6 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
(decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6);
ipv4 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV4;
ipv6 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV6;
if (ipv4 &&
(rx_error & (BIT(I40E_RX_DESC_ERROR_IPE_SHIFT) |
......@@ -1800,49 +1793,16 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
* we need to bump the checksum level by 1 to reflect the fact that
* we are indicating we validated the inner checksum.
*/
if (decoded.tunnel_type >= I40E_RX_PTYPE_TUNNEL_IP_GRENAT)
if (decoded.tunnel_type >= LIBETH_RX_PT_TUNNEL_IP_GRENAT)
skb->csum_level = 1;
/* Only report checksum unnecessary for TCP, UDP, or SCTP */
switch (decoded.inner_prot) {
case I40E_RX_PTYPE_INNER_PROT_TCP:
case I40E_RX_PTYPE_INNER_PROT_UDP:
case I40E_RX_PTYPE_INNER_PROT_SCTP:
skb->ip_summed = CHECKSUM_UNNECESSARY;
fallthrough;
default:
break;
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
return;
checksum_fail:
vsi->back->hw_csum_rx_error++;
}
/**
* i40e_ptype_to_htype - get a hash type
* @ptype: the ptype value from the descriptor
*
* Returns a hash type to be used by skb_set_hash
**/
static inline int i40e_ptype_to_htype(u8 ptype)
{
struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
if (!decoded.known)
return PKT_HASH_TYPE_NONE;
if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4)
return PKT_HASH_TYPE_L4;
else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3)
return PKT_HASH_TYPE_L3;
else
return PKT_HASH_TYPE_L2;
}
/**
* i40e_rx_hash - set the hash value in the skb
* @ring: descriptor ring
......@@ -1855,17 +1815,19 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
struct sk_buff *skb,
u8 rx_ptype)
{
struct libeth_rx_pt decoded;
u32 hash;
const __le64 rss_mask =
cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
if (!(ring->netdev->features & NETIF_F_RXHASH))
decoded = libie_rx_pt_parse(rx_ptype);
if (!libeth_rx_pt_has_hash(ring->netdev, decoded))
return;
if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype));
libeth_rx_pt_set_hash(skb, hash, decoded);
}
}
......
......@@ -745,94 +745,6 @@ enum i40e_rx_desc_error_l3l4e_fcoe_masks {
#define I40E_RXD_QW1_PTYPE_SHIFT 30
#define I40E_RXD_QW1_PTYPE_MASK (0xFFULL << I40E_RXD_QW1_PTYPE_SHIFT)
/* 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_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 {
u32 known:1;
u32 outer_ip:1;
u32 outer_ip_ver:1;
u32 outer_frag:1;
u32 tunnel_type:3;
u32 tunnel_end_prot:2;
u32 tunnel_end_frag:1;
u32 inner_prot:4;
u32 payload_layer:3;
};
enum i40e_rx_ptype_outer_ip {
I40E_RX_PTYPE_OUTER_L2 = 0,
I40E_RX_PTYPE_OUTER_IP = 1
};
enum i40e_rx_ptype_outer_ip_ver {
I40E_RX_PTYPE_OUTER_NONE = 0,
I40E_RX_PTYPE_OUTER_IPV4 = 0,
I40E_RX_PTYPE_OUTER_IPV6 = 1
};
enum i40e_rx_ptype_outer_fragmented {
I40E_RX_PTYPE_NOT_FRAG = 0,
I40E_RX_PTYPE_FRAG = 1
};
enum i40e_rx_ptype_tunnel_type {
I40E_RX_PTYPE_TUNNEL_NONE = 0,
I40E_RX_PTYPE_TUNNEL_IP_IP = 1,
I40E_RX_PTYPE_TUNNEL_IP_GRENAT = 2,
I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3,
I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4,
};
enum i40e_rx_ptype_tunnel_end_prot {
I40E_RX_PTYPE_TUNNEL_END_NONE = 0,
I40E_RX_PTYPE_TUNNEL_END_IPV4 = 1,
I40E_RX_PTYPE_TUNNEL_END_IPV6 = 2,
};
enum i40e_rx_ptype_inner_prot {
I40E_RX_PTYPE_INNER_PROT_NONE = 0,
I40E_RX_PTYPE_INNER_PROT_UDP = 1,
I40E_RX_PTYPE_INNER_PROT_TCP = 2,
I40E_RX_PTYPE_INNER_PROT_SCTP = 3,
I40E_RX_PTYPE_INNER_PROT_ICMP = 4,
I40E_RX_PTYPE_INNER_PROT_TIMESYNC = 5
};
enum i40e_rx_ptype_payload_layer {
I40E_RX_PTYPE_PAYLOAD_LAYER_NONE = 0,
I40E_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1,
I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2,
I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3,
};
#define I40E_RXD_QW1_LENGTH_PBUF_SHIFT 38
#define I40E_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \
I40E_RXD_QW1_LENGTH_PBUF_SHIFT)
......
......@@ -45,6 +45,7 @@ MODULE_DEVICE_TABLE(pci, iavf_pci_tbl);
MODULE_ALIAS("i40evf");
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) Ethernet Adaptive Virtual Function Network Driver");
MODULE_IMPORT_NS(LIBIE);
MODULE_LICENSE("GPL v2");
static const struct net_device_ops iavf_netdev_ops;
......
......@@ -45,13 +45,6 @@ enum iavf_status iavf_aq_set_rss_lut(struct iavf_hw *hw, u16 seid,
enum iavf_status iavf_aq_set_rss_key(struct iavf_hw *hw, u16 seid,
struct iavf_aqc_get_set_rss_key_data *key);
extern struct iavf_rx_ptype_decoded iavf_ptype_lookup[];
static inline struct iavf_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
{
return iavf_ptype_lookup[ptype];
}
void iavf_vf_parse_hw_config(struct iavf_hw *hw,
struct virtchnl_vf_resource *msg);
enum iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw,
......
......@@ -2,6 +2,7 @@
/* Copyright(c) 2013 - 2018 Intel Corporation. */
#include <linux/bitfield.h>
#include <linux/net/intel/libie/rx.h>
#include <linux/prefetch.h>
#include "iavf.h"
......@@ -982,38 +983,30 @@ static void iavf_rx_checksum(struct iavf_vsi *vsi,
struct sk_buff *skb,
union iavf_rx_desc *rx_desc)
{
struct iavf_rx_ptype_decoded decoded;
struct libeth_rx_pt decoded;
u32 rx_error, rx_status;
bool ipv4, ipv6;
u8 ptype;
u64 qword;
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
ptype = FIELD_GET(IAVF_RXD_QW1_PTYPE_MASK, qword);
rx_error = FIELD_GET(IAVF_RXD_QW1_ERROR_MASK, qword);
rx_status = FIELD_GET(IAVF_RXD_QW1_STATUS_MASK, qword);
decoded = decode_rx_desc_ptype(ptype);
skb->ip_summed = CHECKSUM_NONE;
skb_checksum_none_assert(skb);
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
ptype = FIELD_GET(IAVF_RXD_QW1_PTYPE_MASK, qword);
/* Rx csum enabled and ip headers found? */
if (!(vsi->netdev->features & NETIF_F_RXCSUM))
decoded = libie_rx_pt_parse(ptype);
if (!libeth_rx_pt_has_checksum(vsi->netdev, decoded))
return;
rx_error = FIELD_GET(IAVF_RXD_QW1_ERROR_MASK, qword);
rx_status = FIELD_GET(IAVF_RXD_QW1_STATUS_MASK, qword);
/* did the hardware decode the packet and checksum? */
if (!(rx_status & BIT(IAVF_RX_DESC_STATUS_L3L4P_SHIFT)))
return;
/* both known and outer_ip must be set for the below code to work */
if (!(decoded.known && decoded.outer_ip))
return;
ipv4 = (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP) &&
(decoded.outer_ip_ver == IAVF_RX_PTYPE_OUTER_IPV4);
ipv6 = (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP) &&
(decoded.outer_ip_ver == IAVF_RX_PTYPE_OUTER_IPV6);
ipv4 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV4;
ipv6 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV6;
if (ipv4 &&
(rx_error & (BIT(IAVF_RX_DESC_ERROR_IPE_SHIFT) |
......@@ -1037,46 +1030,13 @@ static void iavf_rx_checksum(struct iavf_vsi *vsi,
if (rx_error & BIT(IAVF_RX_DESC_ERROR_PPRS_SHIFT))
return;
/* Only report checksum unnecessary for TCP, UDP, or SCTP */
switch (decoded.inner_prot) {
case IAVF_RX_PTYPE_INNER_PROT_TCP:
case IAVF_RX_PTYPE_INNER_PROT_UDP:
case IAVF_RX_PTYPE_INNER_PROT_SCTP:
skb->ip_summed = CHECKSUM_UNNECESSARY;
fallthrough;
default:
break;
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
return;
checksum_fail:
vsi->back->hw_csum_rx_error++;
}
/**
* iavf_ptype_to_htype - get a hash type
* @ptype: the ptype value from the descriptor
*
* Returns a hash type to be used by skb_set_hash
**/
static int iavf_ptype_to_htype(u8 ptype)
{
struct iavf_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
if (!decoded.known)
return PKT_HASH_TYPE_NONE;
if (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY4)
return PKT_HASH_TYPE_L4;
else if (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY3)
return PKT_HASH_TYPE_L3;
else
return PKT_HASH_TYPE_L2;
}
/**
* iavf_rx_hash - set the hash value in the skb
* @ring: descriptor ring
......@@ -1089,17 +1049,19 @@ static void iavf_rx_hash(struct iavf_ring *ring,
struct sk_buff *skb,
u8 rx_ptype)
{
struct libeth_rx_pt decoded;
u32 hash;
const __le64 rss_mask =
cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<
IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT);
if (!(ring->netdev->features & NETIF_F_RXHASH))
decoded = libie_rx_pt_parse(rx_ptype);
if (!libeth_rx_pt_has_hash(ring->netdev, decoded))
return;
if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
skb_set_hash(skb, hash, iavf_ptype_to_htype(rx_ptype));
libeth_rx_pt_set_hash(skb, hash, decoded);
}
}
......
......@@ -327,94 +327,6 @@ enum iavf_rx_desc_error_l3l4e_fcoe_masks {
#define IAVF_RXD_QW1_PTYPE_SHIFT 30
#define IAVF_RXD_QW1_PTYPE_MASK (0xFFULL << IAVF_RXD_QW1_PTYPE_SHIFT)
/* Packet type non-ip values */
enum iavf_rx_l2_ptype {
IAVF_RX_PTYPE_L2_RESERVED = 0,
IAVF_RX_PTYPE_L2_MAC_PAY2 = 1,
IAVF_RX_PTYPE_L2_TIMESYNC_PAY2 = 2,
IAVF_RX_PTYPE_L2_FIP_PAY2 = 3,
IAVF_RX_PTYPE_L2_OUI_PAY2 = 4,
IAVF_RX_PTYPE_L2_MACCNTRL_PAY2 = 5,
IAVF_RX_PTYPE_L2_LLDP_PAY2 = 6,
IAVF_RX_PTYPE_L2_ECP_PAY2 = 7,
IAVF_RX_PTYPE_L2_EVB_PAY2 = 8,
IAVF_RX_PTYPE_L2_QCN_PAY2 = 9,
IAVF_RX_PTYPE_L2_EAPOL_PAY2 = 10,
IAVF_RX_PTYPE_L2_ARP = 11,
IAVF_RX_PTYPE_L2_FCOE_PAY3 = 12,
IAVF_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13,
IAVF_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14,
IAVF_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15,
IAVF_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16,
IAVF_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17,
IAVF_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18,
IAVF_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19,
IAVF_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20,
IAVF_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21,
IAVF_RX_PTYPE_GRENAT4_MAC_PAY3 = 58,
IAVF_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87,
IAVF_RX_PTYPE_GRENAT6_MAC_PAY3 = 124,
IAVF_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153
};
struct iavf_rx_ptype_decoded {
u32 known:1;
u32 outer_ip:1;
u32 outer_ip_ver:1;
u32 outer_frag:1;
u32 tunnel_type:3;
u32 tunnel_end_prot:2;
u32 tunnel_end_frag:1;
u32 inner_prot:4;
u32 payload_layer:3;
};
enum iavf_rx_ptype_outer_ip {
IAVF_RX_PTYPE_OUTER_L2 = 0,
IAVF_RX_PTYPE_OUTER_IP = 1
};
enum iavf_rx_ptype_outer_ip_ver {
IAVF_RX_PTYPE_OUTER_NONE = 0,
IAVF_RX_PTYPE_OUTER_IPV4 = 0,
IAVF_RX_PTYPE_OUTER_IPV6 = 1
};
enum iavf_rx_ptype_outer_fragmented {
IAVF_RX_PTYPE_NOT_FRAG = 0,
IAVF_RX_PTYPE_FRAG = 1
};
enum iavf_rx_ptype_tunnel_type {
IAVF_RX_PTYPE_TUNNEL_NONE = 0,
IAVF_RX_PTYPE_TUNNEL_IP_IP = 1,
IAVF_RX_PTYPE_TUNNEL_IP_GRENAT = 2,
IAVF_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3,
IAVF_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4,
};
enum iavf_rx_ptype_tunnel_end_prot {
IAVF_RX_PTYPE_TUNNEL_END_NONE = 0,
IAVF_RX_PTYPE_TUNNEL_END_IPV4 = 1,
IAVF_RX_PTYPE_TUNNEL_END_IPV6 = 2,
};
enum iavf_rx_ptype_inner_prot {
IAVF_RX_PTYPE_INNER_PROT_NONE = 0,
IAVF_RX_PTYPE_INNER_PROT_UDP = 1,
IAVF_RX_PTYPE_INNER_PROT_TCP = 2,
IAVF_RX_PTYPE_INNER_PROT_SCTP = 3,
IAVF_RX_PTYPE_INNER_PROT_ICMP = 4,
IAVF_RX_PTYPE_INNER_PROT_TIMESYNC = 5
};
enum iavf_rx_ptype_payload_layer {
IAVF_RX_PTYPE_PAYLOAD_LAYER_NONE = 0,
IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1,
IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2,
IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3,
};
#define IAVF_RXD_QW1_LENGTH_PBUF_SHIFT 38
#define IAVF_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \
IAVF_RXD_QW1_LENGTH_PBUF_SHIFT)
......
......@@ -37,6 +37,7 @@ static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation.";
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION(DRV_SUMMARY);
MODULE_IMPORT_NS(LIBIE);
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(ICE_DDP_PKG_FILE);
......
......@@ -2,6 +2,7 @@
/* Copyright (c) 2019, Intel Corporation. */
#include <linux/filter.h>
#include <linux/net/intel/libie/rx.h>
#include "ice_txrx_lib.h"
#include "ice_eswitch.h"
......@@ -38,30 +39,6 @@ void ice_release_rx_desc(struct ice_rx_ring *rx_ring, u16 val)
}
}
/**
* ice_ptype_to_htype - get a hash type
* @ptype: the ptype value from the descriptor
*
* Returns appropriate hash type (such as PKT_HASH_TYPE_L2/L3/L4) to be used by
* skb_set_hash based on PTYPE as parsed by HW Rx pipeline and is part of
* Rx desc.
*/
static enum pkt_hash_types ice_ptype_to_htype(u16 ptype)
{
struct ice_rx_ptype_decoded decoded = ice_decode_rx_desc_ptype(ptype);
if (!decoded.known)
return PKT_HASH_TYPE_NONE;
if (decoded.payload_layer == ICE_RX_PTYPE_PAYLOAD_LAYER_PAY4)
return PKT_HASH_TYPE_L4;
if (decoded.payload_layer == ICE_RX_PTYPE_PAYLOAD_LAYER_PAY3)
return PKT_HASH_TYPE_L3;
if (decoded.outer_ip == ICE_RX_PTYPE_OUTER_L2)
return PKT_HASH_TYPE_L2;
return PKT_HASH_TYPE_NONE;
}
/**
* ice_get_rx_hash - get RX hash value from descriptor
* @rx_desc: specific descriptor
......@@ -91,14 +68,16 @@ ice_rx_hash_to_skb(const struct ice_rx_ring *rx_ring,
const union ice_32b_rx_flex_desc *rx_desc,
struct sk_buff *skb, u16 rx_ptype)
{
struct libeth_rx_pt decoded;
u32 hash;
if (!(rx_ring->netdev->features & NETIF_F_RXHASH))
decoded = libie_rx_pt_parse(rx_ptype);
if (!libeth_rx_pt_has_hash(rx_ring->netdev, decoded))
return;
hash = ice_get_rx_hash(rx_desc);
if (likely(hash))
skb_set_hash(skb, hash, ice_ptype_to_htype(rx_ptype));
libeth_rx_pt_set_hash(skb, hash, decoded);
}
/**
......@@ -114,34 +93,26 @@ static void
ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
union ice_32b_rx_flex_desc *rx_desc, u16 ptype)
{
struct ice_rx_ptype_decoded decoded;
struct libeth_rx_pt decoded;
u16 rx_status0, rx_status1;
bool ipv4, ipv6;
rx_status0 = le16_to_cpu(rx_desc->wb.status_error0);
rx_status1 = le16_to_cpu(rx_desc->wb.status_error1);
decoded = ice_decode_rx_desc_ptype(ptype);
/* Start with CHECKSUM_NONE and by default csum_level = 0 */
skb->ip_summed = CHECKSUM_NONE;
skb_checksum_none_assert(skb);
/* check if Rx checksum is enabled */
if (!(ring->netdev->features & NETIF_F_RXCSUM))
decoded = libie_rx_pt_parse(ptype);
if (!libeth_rx_pt_has_checksum(ring->netdev, decoded))
return;
rx_status0 = le16_to_cpu(rx_desc->wb.status_error0);
rx_status1 = le16_to_cpu(rx_desc->wb.status_error1);
/* check if HW has decoded the packet and checksum */
if (!(rx_status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S)))
return;
if (!(decoded.known && decoded.outer_ip))
return;
ipv4 = (decoded.outer_ip == ICE_RX_PTYPE_OUTER_IP) &&
(decoded.outer_ip_ver == ICE_RX_PTYPE_OUTER_IPV4);
ipv6 = (decoded.outer_ip == ICE_RX_PTYPE_OUTER_IP) &&
(decoded.outer_ip_ver == ICE_RX_PTYPE_OUTER_IPV6);
ipv4 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV4;
ipv6 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV6;
if (ipv4 && (rx_status0 & (BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_EIPE_S)))) {
ring->vsi->back->hw_rx_eipe_error++;
......@@ -169,19 +140,10 @@ ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
* we need to bump the checksum level by 1 to reflect the fact that
* we are indicating we validated the inner checksum.
*/
if (decoded.tunnel_type >= ICE_RX_PTYPE_TUNNEL_IP_GRENAT)
if (decoded.tunnel_type >= LIBETH_RX_PT_TUNNEL_IP_GRENAT)
skb->csum_level = 1;
/* Only report checksum unnecessary for TCP, UDP, or SCTP */
switch (decoded.inner_prot) {
case ICE_RX_PTYPE_INNER_PROT_TCP:
case ICE_RX_PTYPE_INNER_PROT_UDP:
case ICE_RX_PTYPE_INNER_PROT_SCTP:
skb->ip_summed = CHECKSUM_UNNECESSARY;
break;
default:
break;
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
return;
checksum_fail:
......@@ -536,42 +498,6 @@ static int ice_xdp_rx_hw_ts(const struct xdp_md *ctx, u64 *ts_ns)
return 0;
}
/* Define a ptype index -> XDP hash type lookup table.
* It uses the same ptype definitions as ice_decode_rx_desc_ptype[],
* avoiding possible copy-paste errors.
*/
#undef ICE_PTT
#undef ICE_PTT_UNUSED_ENTRY
#define ICE_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
[PTYPE] = XDP_RSS_L3_##OUTER_IP_VER | XDP_RSS_L4_##I | XDP_RSS_TYPE_##PL
#define ICE_PTT_UNUSED_ENTRY(PTYPE) [PTYPE] = 0
/* A few supplementary definitions for when XDP hash types do not coincide
* with what can be generated from ptype definitions
* by means of preprocessor concatenation.
*/
#define XDP_RSS_L3_NONE XDP_RSS_TYPE_NONE
#define XDP_RSS_L4_NONE XDP_RSS_TYPE_NONE
#define XDP_RSS_TYPE_PAY2 XDP_RSS_TYPE_L2
#define XDP_RSS_TYPE_PAY3 XDP_RSS_TYPE_NONE
#define XDP_RSS_TYPE_PAY4 XDP_RSS_L4
static const enum xdp_rss_hash_type
ice_ptype_to_xdp_hash[ICE_NUM_DEFINED_PTYPES] = {
ICE_PTYPES
};
#undef XDP_RSS_L3_NONE
#undef XDP_RSS_L4_NONE
#undef XDP_RSS_TYPE_PAY2
#undef XDP_RSS_TYPE_PAY3
#undef XDP_RSS_TYPE_PAY4
#undef ICE_PTT
#undef ICE_PTT_UNUSED_ENTRY
/**
* ice_xdp_rx_hash_type - Get XDP-specific hash type from the RX descriptor
* @eop_desc: End of Packet descriptor
......@@ -579,12 +505,7 @@ ice_ptype_to_xdp_hash[ICE_NUM_DEFINED_PTYPES] = {
static enum xdp_rss_hash_type
ice_xdp_rx_hash_type(const union ice_32b_rx_flex_desc *eop_desc)
{
u16 ptype = ice_get_ptype(eop_desc);
if (unlikely(ptype >= ICE_NUM_DEFINED_PTYPES))
return 0;
return ice_ptype_to_xdp_hash[ptype];
return libie_rx_pt_parse(ice_get_ptype(eop_desc)).hash_type;
}
/**
......
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2024 Intel Corporation
config LIBETH
tristate
help
libeth is a common library containing routines shared between several
drivers, but not yet promoted to the generic kernel API.
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2024 Intel Corporation
obj-$(CONFIG_LIBETH) += libeth.o
libeth-objs += rx.o
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2024 Intel Corporation */
#include <net/libeth/rx.h>
/* Converting abstract packet type numbers into a software structure with
* the packet parameters to do O(1) lookup on Rx.
*/
static const u16 libeth_rx_pt_xdp_oip[] = {
[LIBETH_RX_PT_OUTER_L2] = XDP_RSS_TYPE_NONE,
[LIBETH_RX_PT_OUTER_IPV4] = XDP_RSS_L3_IPV4,
[LIBETH_RX_PT_OUTER_IPV6] = XDP_RSS_L3_IPV6,
};
static const u16 libeth_rx_pt_xdp_iprot[] = {
[LIBETH_RX_PT_INNER_NONE] = XDP_RSS_TYPE_NONE,
[LIBETH_RX_PT_INNER_UDP] = XDP_RSS_L4_UDP,
[LIBETH_RX_PT_INNER_TCP] = XDP_RSS_L4_TCP,
[LIBETH_RX_PT_INNER_SCTP] = XDP_RSS_L4_SCTP,
[LIBETH_RX_PT_INNER_ICMP] = XDP_RSS_L4_ICMP,
[LIBETH_RX_PT_INNER_TIMESYNC] = XDP_RSS_TYPE_NONE,
};
static const u16 libeth_rx_pt_xdp_pl[] = {
[LIBETH_RX_PT_PAYLOAD_NONE] = XDP_RSS_TYPE_NONE,
[LIBETH_RX_PT_PAYLOAD_L2] = XDP_RSS_TYPE_NONE,
[LIBETH_RX_PT_PAYLOAD_L3] = XDP_RSS_TYPE_NONE,
[LIBETH_RX_PT_PAYLOAD_L4] = XDP_RSS_L4,
};
/**
* libeth_rx_pt_gen_hash_type - generate an XDP RSS hash type for a PT
* @pt: PT structure to evaluate
*
* Generates ```hash_type``` field with XDP RSS type values from the parsed
* packet parameters if they're obtained dynamically at runtime.
*/
void libeth_rx_pt_gen_hash_type(struct libeth_rx_pt *pt)
{
pt->hash_type = 0;
pt->hash_type |= libeth_rx_pt_xdp_oip[pt->outer_ip];
pt->hash_type |= libeth_rx_pt_xdp_iprot[pt->inner_prot];
pt->hash_type |= libeth_rx_pt_xdp_pl[pt->payload_layer];
}
EXPORT_SYMBOL_NS_GPL(libeth_rx_pt_gen_hash_type, LIBETH);
/* Module */
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Common Ethernet library");
MODULE_LICENSE("GPL");
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2024 Intel Corporation
config LIBIE
tristate
select LIBETH
help
libie (Intel Ethernet library) is a common library built on top of
libeth and containing vendor-specific routines shared between several
Intel Ethernet drivers.
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2024 Intel Corporation
obj-$(CONFIG_LIBIE) += libie.o
libie-objs += rx.o
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2024 Intel Corporation */
#include <linux/net/intel/libie/rx.h>
/* O(1) converting i40e/ice/iavf's 8/10-bit hardware packet type to a parsed
* bitfield struct.
*/
/* A few supplementary definitions for when XDP hash types do not coincide
* with what can be generated from ptype definitions by means of preprocessor
* concatenation.
*/
#define XDP_RSS_L3_L2 XDP_RSS_TYPE_NONE
#define XDP_RSS_L4_NONE XDP_RSS_TYPE_NONE
#define XDP_RSS_L4_TIMESYNC XDP_RSS_TYPE_NONE
#define XDP_RSS_TYPE_L3 XDP_RSS_TYPE_NONE
#define XDP_RSS_TYPE_L4 XDP_RSS_L4
#define LIBIE_RX_PT(oip, ofrag, tun, tp, tefr, iprot, pl) { \
.outer_ip = LIBETH_RX_PT_OUTER_##oip, \
.outer_frag = LIBETH_RX_PT_##ofrag, \
.tunnel_type = LIBETH_RX_PT_TUNNEL_IP_##tun, \
.tunnel_end_prot = LIBETH_RX_PT_TUNNEL_END_##tp, \
.tunnel_end_frag = LIBETH_RX_PT_##tefr, \
.inner_prot = LIBETH_RX_PT_INNER_##iprot, \
.payload_layer = LIBETH_RX_PT_PAYLOAD_##pl, \
.hash_type = XDP_RSS_L3_##oip | \
XDP_RSS_L4_##iprot | \
XDP_RSS_TYPE_##pl, \
}
#define LIBIE_RX_PT_UNUSED { }
#define __LIBIE_RX_PT_L2(iprot, pl) \
LIBIE_RX_PT(L2, NOT_FRAG, NONE, NONE, NOT_FRAG, iprot, pl)
#define LIBIE_RX_PT_L2 __LIBIE_RX_PT_L2(NONE, L2)
#define LIBIE_RX_PT_TS __LIBIE_RX_PT_L2(TIMESYNC, L2)
#define LIBIE_RX_PT_L3 __LIBIE_RX_PT_L2(NONE, L3)
#define LIBIE_RX_PT_IP_FRAG(oip) \
LIBIE_RX_PT(IPV##oip, FRAG, NONE, NONE, NOT_FRAG, NONE, L3)
#define LIBIE_RX_PT_IP_L3(oip, tun, teprot, tefr) \
LIBIE_RX_PT(IPV##oip, NOT_FRAG, tun, teprot, tefr, NONE, L3)
#define LIBIE_RX_PT_IP_L4(oip, tun, teprot, iprot) \
LIBIE_RX_PT(IPV##oip, NOT_FRAG, tun, teprot, NOT_FRAG, iprot, L4)
#define LIBIE_RX_PT_IP_NOF(oip, tun, ver) \
LIBIE_RX_PT_IP_L3(oip, tun, ver, NOT_FRAG), \
LIBIE_RX_PT_IP_L4(oip, tun, ver, UDP), \
LIBIE_RX_PT_UNUSED, \
LIBIE_RX_PT_IP_L4(oip, tun, ver, TCP), \
LIBIE_RX_PT_IP_L4(oip, tun, ver, SCTP), \
LIBIE_RX_PT_IP_L4(oip, tun, ver, ICMP)
/* IPv oip --> tun --> IPv ver */
#define LIBIE_RX_PT_IP_TUN_VER(oip, tun, ver) \
LIBIE_RX_PT_IP_L3(oip, tun, ver, FRAG), \
LIBIE_RX_PT_IP_NOF(oip, tun, ver)
/* Non Tunneled IPv oip */
#define LIBIE_RX_PT_IP_RAW(oip) \
LIBIE_RX_PT_IP_FRAG(oip), \
LIBIE_RX_PT_IP_NOF(oip, NONE, NONE)
/* IPv oip --> tun --> { IPv4, IPv6 } */
#define LIBIE_RX_PT_IP_TUN(oip, tun) \
LIBIE_RX_PT_IP_TUN_VER(oip, tun, IPV4), \
LIBIE_RX_PT_IP_TUN_VER(oip, tun, IPV6)
/* IPv oip --> GRE/NAT tun --> { x, IPv4, IPv6 } */
#define LIBIE_RX_PT_IP_GRE(oip, tun) \
LIBIE_RX_PT_IP_L3(oip, tun, NONE, NOT_FRAG), \
LIBIE_RX_PT_IP_TUN(oip, tun)
/* Non Tunneled IPv oip
* IPv oip --> { IPv4, IPv6 }
* IPv oip --> GRE/NAT --> { x, IPv4, IPv6 }
* IPv oip --> GRE/NAT --> MAC --> { x, IPv4, IPv6 }
* IPv oip --> GRE/NAT --> MAC/VLAN --> { x, IPv4, IPv6 }
*/
#define LIBIE_RX_PT_IP(oip) \
LIBIE_RX_PT_IP_RAW(oip), \
LIBIE_RX_PT_IP_TUN(oip, IP), \
LIBIE_RX_PT_IP_GRE(oip, GRENAT), \
LIBIE_RX_PT_IP_GRE(oip, GRENAT_MAC), \
LIBIE_RX_PT_IP_GRE(oip, GRENAT_MAC_VLAN)
/* Lookup table mapping for O(1) parsing */
const struct libeth_rx_pt libie_rx_pt_lut[LIBIE_RX_PT_NUM] = {
/* L2 packet types */
LIBIE_RX_PT_UNUSED,
LIBIE_RX_PT_L2,
LIBIE_RX_PT_TS,
LIBIE_RX_PT_L2,
LIBIE_RX_PT_UNUSED,
LIBIE_RX_PT_UNUSED,
LIBIE_RX_PT_L2,
LIBIE_RX_PT_L2,
LIBIE_RX_PT_UNUSED,
LIBIE_RX_PT_UNUSED,
LIBIE_RX_PT_L2,
LIBIE_RX_PT_UNUSED,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_L3,
LIBIE_RX_PT_IP(4),
LIBIE_RX_PT_IP(6),
};
EXPORT_SYMBOL_NS_GPL(libie_rx_pt_lut, LIBIE);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Intel(R) Ethernet common library");
MODULE_IMPORT_NS(LIBETH);
MODULE_LICENSE("GPL");
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2024 Intel Corporation */
#ifndef __LIBIE_RX_H
#define __LIBIE_RX_H
#include <net/libeth/rx.h>
/* O(1) converting i40e/ice/iavf's 8/10-bit hardware packet type to a parsed
* bitfield struct.
*/
#define LIBIE_RX_PT_NUM 154
extern const struct libeth_rx_pt libie_rx_pt_lut[LIBIE_RX_PT_NUM];
/**
* libie_rx_pt_parse - convert HW packet type to software bitfield structure
* @pt: 10-bit hardware packet type value from the descriptor
*
* ```libie_rx_pt_lut``` must be accessed only using this wrapper.
*
* Return: parsed bitfield struct corresponding to the provided ptype.
*/
static inline struct libeth_rx_pt libie_rx_pt_parse(u32 pt)
{
if (unlikely(pt >= LIBIE_RX_PT_NUM))
pt = 0;
return libie_rx_pt_lut[pt];
}
#endif /* __LIBIE_RX_H */
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2024 Intel Corporation */
#ifndef __LIBETH_RX_H
#define __LIBETH_RX_H
#include <net/xdp.h>
/* Converting abstract packet type numbers into a software structure with
* the packet parameters to do O(1) lookup on Rx.
*/
enum {
LIBETH_RX_PT_OUTER_L2 = 0U,
LIBETH_RX_PT_OUTER_IPV4,
LIBETH_RX_PT_OUTER_IPV6,
};
enum {
LIBETH_RX_PT_NOT_FRAG = 0U,
LIBETH_RX_PT_FRAG,
};
enum {
LIBETH_RX_PT_TUNNEL_IP_NONE = 0U,
LIBETH_RX_PT_TUNNEL_IP_IP,
LIBETH_RX_PT_TUNNEL_IP_GRENAT,
LIBETH_RX_PT_TUNNEL_IP_GRENAT_MAC,
LIBETH_RX_PT_TUNNEL_IP_GRENAT_MAC_VLAN,
};
enum {
LIBETH_RX_PT_TUNNEL_END_NONE = 0U,
LIBETH_RX_PT_TUNNEL_END_IPV4,
LIBETH_RX_PT_TUNNEL_END_IPV6,
};
enum {
LIBETH_RX_PT_INNER_NONE = 0U,
LIBETH_RX_PT_INNER_UDP,
LIBETH_RX_PT_INNER_TCP,
LIBETH_RX_PT_INNER_SCTP,
LIBETH_RX_PT_INNER_ICMP,
LIBETH_RX_PT_INNER_TIMESYNC,
};
#define LIBETH_RX_PT_PAYLOAD_NONE PKT_HASH_TYPE_NONE
#define LIBETH_RX_PT_PAYLOAD_L2 PKT_HASH_TYPE_L2
#define LIBETH_RX_PT_PAYLOAD_L3 PKT_HASH_TYPE_L3
#define LIBETH_RX_PT_PAYLOAD_L4 PKT_HASH_TYPE_L4
struct libeth_rx_pt {
u32 outer_ip:2;
u32 outer_frag:1;
u32 tunnel_type:3;
u32 tunnel_end_prot:2;
u32 tunnel_end_frag:1;
u32 inner_prot:3;
enum pkt_hash_types payload_layer:2;
u32 pad:2;
enum xdp_rss_hash_type hash_type:16;
};
void libeth_rx_pt_gen_hash_type(struct libeth_rx_pt *pt);
/**
* libeth_rx_pt_get_ip_ver - get IP version from a packet type structure
* @pt: packet type params
*
* Wrapper to compile out the IPv6 code from the drivers when not supported
* by the kernel.
*
* Return: @pt.outer_ip or stub for IPv6 when not compiled-in.
*/
static inline u32 libeth_rx_pt_get_ip_ver(struct libeth_rx_pt pt)
{
#if !IS_ENABLED(CONFIG_IPV6)
switch (pt.outer_ip) {
case LIBETH_RX_PT_OUTER_IPV4:
return LIBETH_RX_PT_OUTER_IPV4;
default:
return LIBETH_RX_PT_OUTER_L2;
}
#else
return pt.outer_ip;
#endif
}
/* libeth_has_*() can be used to quickly check whether the HW metadata is
* available to avoid further expensive processing such as descriptor reads.
* They already check for the corresponding netdev feature to be enabled,
* thus can be used as drop-in replacements.
*/
static inline bool libeth_rx_pt_has_checksum(const struct net_device *dev,
struct libeth_rx_pt pt)
{
/* Non-zero _INNER* is only possible when _OUTER_IPV* is set,
* it is enough to check only for the L4 type.
*/
return likely(pt.inner_prot > LIBETH_RX_PT_INNER_NONE &&
(dev->features & NETIF_F_RXCSUM));
}
static inline bool libeth_rx_pt_has_hash(const struct net_device *dev,
struct libeth_rx_pt pt)
{
return likely(pt.payload_layer > LIBETH_RX_PT_PAYLOAD_NONE &&
(dev->features & NETIF_F_RXHASH));
}
/**
* libeth_rx_pt_set_hash - fill in skb hash value basing on the PT
* @skb: skb to fill the hash in
* @hash: 32-bit hash value from the descriptor
* @pt: packet type
*/
static inline void libeth_rx_pt_set_hash(struct sk_buff *skb, u32 hash,
struct libeth_rx_pt pt)
{
skb_set_hash(skb, hash, pt.payload_layer);
}
#endif /* __LIBETH_RX_H */
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