Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Documentation/netlink/specs/netdev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ definitions:
doc: |
Device is capable of exposing receive packet VLAN tag via
bpf_xdp_metadata_rx_vlan_tag().
-
name: checksum
doc: |
Device is capable of exposing receive checksum result via
bpf_xdp_metadata_rx_checksum().
-
type: flags
name: xsk-flags
Expand Down
118 changes: 76 additions & 42 deletions drivers/net/ethernet/intel/ice/ice_txrx_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,69 +78,47 @@ ice_rx_hash_to_skb(const struct ice_rx_ring *rx_ring,
libeth_rx_pt_set_hash(skb, hash, decoded);
}

/**
* ice_rx_gcs - Set generic checksum in skb
* @skb: skb currently being received and modified
* @rx_desc: receive descriptor
*/
static void ice_rx_gcs(struct sk_buff *skb,
const union ice_32b_rx_flex_desc *rx_desc)
{
const struct ice_32b_rx_flex_desc_nic *desc;
u16 csum;

desc = (struct ice_32b_rx_flex_desc_nic *)rx_desc;
skb->ip_summed = CHECKSUM_COMPLETE;
csum = (__force u16)desc->raw_csum;
skb->csum = csum_unfold((__force __sum16)swab16(csum));
}

/**
* ice_rx_csum - Indicate in skb if checksum is good
* @ring: the ring we care about
* @skb: skb currently being received and modified
* @rx_desc: the receive descriptor
* @ptype: the packet type decoded by hardware
*
* skb->protocol must be set before this function is called
*/
static void
ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
union ice_32b_rx_flex_desc *rx_desc, u16 ptype)
ice_get_rx_csum(const union ice_32b_rx_flex_desc *rx_desc, u16 ptype,
struct ice_rx_ring *ring, enum xdp_checksum *ip_summed,
u32 *cksum_meta)
{
struct libeth_rx_pt decoded;
struct libeth_rx_pt decoded = libie_rx_pt_parse(ptype);
u16 rx_status0, rx_status1;
bool ipv4, ipv6;

/* Start with CHECKSUM_NONE and by default csum_level = 0 */
skb->ip_summed = CHECKSUM_NONE;

decoded = libie_rx_pt_parse(ptype);
if (!libeth_rx_pt_has_checksum(ring->netdev, decoded))
return;
goto checksum_none;

rx_status0 = le16_to_cpu(rx_desc->wb.status_error0);
rx_status1 = le16_to_cpu(rx_desc->wb.status_error1);

if ((ring->flags & ICE_RX_FLAGS_RING_GCS) &&
rx_desc->wb.rxdid == ICE_RXDID_FLEX_NIC &&
(decoded.inner_prot == LIBETH_RX_PT_INNER_TCP ||
decoded.inner_prot == LIBETH_RX_PT_INNER_UDP ||
decoded.inner_prot == LIBETH_RX_PT_INNER_ICMP)) {
ice_rx_gcs(skb, rx_desc);
const struct ice_32b_rx_flex_desc_nic *desc;
__wsum wcsum;
u16 csum;

desc = (struct ice_32b_rx_flex_desc_nic *)rx_desc;
*ip_summed = XDP_CHECKSUM_COMPLETE;
csum = (__force u16)desc->raw_csum;
wcsum = csum_unfold((__force __sum16)swab16(csum));
*cksum_meta = (__force u32)wcsum;
return;
}

/* check if HW has decoded the packet and checksum */
if (!(rx_status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S)))
return;
goto checksum_none;

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++;
return;
goto checksum_none;
}

if (ipv4 && (rx_status0 & (BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_IPE_S))))
Expand All @@ -164,14 +142,45 @@ 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 >= LIBETH_RX_PT_TUNNEL_IP_GRENAT)
skb->csum_level = 1;

skb->ip_summed = CHECKSUM_UNNECESSARY;
*cksum_meta = decoded.tunnel_type >= LIBETH_RX_PT_TUNNEL_IP_GRENAT;
*ip_summed = XDP_CHECKSUM_UNNECESSARY;
return;

checksum_fail:
ring->vsi->back->hw_csum_rx_error++;
checksum_none:
*ip_summed = XDP_CHECKSUM_NONE;
*cksum_meta = 0;
}

/**
* ice_rx_csum - Indicate in skb if checksum is good
* @ring: the ring we care about
* @skb: skb currently being received and modified
* @rx_desc: the receive descriptor
* @ptype: the packet type decoded by hardware
*
* skb->protocol must be set before this function is called
*/
static void
ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
union ice_32b_rx_flex_desc *rx_desc, u16 ptype)
{
enum xdp_checksum ip_summed;
u32 cksum_meta;

ice_get_rx_csum(rx_desc, ptype, ring, &ip_summed, &cksum_meta);
switch (ip_summed) {
case XDP_CHECKSUM_UNNECESSARY:
skb->csum_level = cksum_meta;
break;
case XDP_CHECKSUM_COMPLETE:
skb->csum = (__force __wsum)cksum_meta;
break;
default:
break;
}
skb->ip_summed = ip_summed;
}

/**
Expand Down Expand Up @@ -566,6 +575,30 @@ static int ice_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
return 0;
}

/**
* ice_xdp_rx_checksum - RX checksum XDP hint handler
* @ctx: XDP buff pointer
* @ip_summed: RX checksum result destination address
* @cksum_meta: XDP RX checksum metadata destination address
*
* Copy RX checksum result (if available) and its metadata to the
* destination address.
*/
static int ice_xdp_rx_checksum(const struct xdp_md *ctx,
enum xdp_checksum *ip_summed,
u32 *cksum_meta)
{
const struct libeth_xdp_buff *xdp_ext = (void *)ctx;
const union ice_32b_rx_flex_desc *rx_desc = xdp_ext->desc;
struct ice_rx_ring *ring;

ring = libeth_xdp_buff_to_rq(xdp_ext, typeof(*ring), xdp_rxq);
ice_get_rx_csum(rx_desc, ice_get_ptype(rx_desc), ring, ip_summed,
cksum_meta);

return 0;
}

/**
* ice_xdp_rx_vlan_tag - VLAN tag XDP hint handler
* @ctx: XDP buff pointer
Expand Down Expand Up @@ -598,4 +631,5 @@ const struct xdp_metadata_ops ice_xdp_md_ops = {
.xmo_rx_timestamp = ice_xdp_rx_hw_ts,
.xmo_rx_hash = ice_xdp_rx_hash,
.xmo_rx_vlan_tag = ice_xdp_rx_vlan_tag,
.xmo_rx_checksum = ice_xdp_rx_checksum,
};
30 changes: 30 additions & 0 deletions drivers/net/veth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,35 @@ static int veth_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto,
return err;
}

static int veth_xdp_rx_checksum(const struct xdp_md *ctx,
enum xdp_checksum *ip_summed,
u32 *cksum_meta)
{
const struct veth_xdp_buff *_ctx = (void *)ctx;
const struct sk_buff *skb = _ctx->skb;

if (!skb)
return -ENODATA;

*ip_summed = skb->ip_summed;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
*ip_summed = XDP_CHECKSUM_COMPLETE;
*cksum_meta = skb->csum;
break;
case CHECKSUM_UNNECESSARY:
*ip_summed = XDP_CHECKSUM_UNNECESSARY;
*cksum_meta = skb->csum_level;
break;
default:
*ip_summed = XDP_CHECKSUM_NONE;
*cksum_meta = 0;
break;
}

return 0;
}

static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init,
.ndo_open = veth_open,
Expand All @@ -1722,6 +1751,7 @@ static const struct xdp_metadata_ops veth_xdp_metadata_ops = {
.xmo_rx_timestamp = veth_xdp_rx_timestamp,
.xmo_rx_hash = veth_xdp_rx_hash,
.xmo_rx_vlan_tag = veth_xdp_rx_vlan_tag,
.xmo_rx_checksum = veth_xdp_rx_checksum,
};

#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \
Expand Down
13 changes: 13 additions & 0 deletions include/net/xdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,10 @@ void xdp_attachment_setup(struct xdp_attachment_info *info,
NETDEV_XDP_RX_METADATA_VLAN_TAG, \
bpf_xdp_metadata_rx_vlan_tag, \
xmo_rx_vlan_tag) \
XDP_METADATA_KFUNC(XDP_METADATA_KFUNC_RX_CHECKSUM, \
NETDEV_XDP_RX_METADATA_CHECKSUM, \
bpf_xdp_metadata_rx_checksum, \
xmo_rx_checksum)

enum xdp_rx_metadata {
#define XDP_METADATA_KFUNC(name, _, __, ___) name,
Expand Down Expand Up @@ -643,12 +647,21 @@ enum xdp_rss_hash_type {
XDP_RSS_TYPE_L4_IPV6_SCTP_EX = XDP_RSS_TYPE_L4_IPV6_SCTP | XDP_RSS_L3_DYNHDR,
};

enum xdp_checksum {
XDP_CHECKSUM_NONE = CHECKSUM_NONE,
XDP_CHECKSUM_UNNECESSARY = CHECKSUM_UNNECESSARY,
XDP_CHECKSUM_COMPLETE = CHECKSUM_COMPLETE,
};

struct xdp_metadata_ops {
int (*xmo_rx_timestamp)(const struct xdp_md *ctx, u64 *timestamp);
int (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash,
enum xdp_rss_hash_type *rss_type);
int (*xmo_rx_vlan_tag)(const struct xdp_md *ctx, __be16 *vlan_proto,
u16 *vlan_tci);
int (*xmo_rx_checksum)(const struct xdp_md *ctx,
enum xdp_checksum *ip_summed,
u32 *cksum_meta);
};

#ifdef CONFIG_NET
Expand Down
3 changes: 3 additions & 0 deletions include/uapi/linux/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ enum netdev_xdp_act {
* hash via bpf_xdp_metadata_rx_hash().
* @NETDEV_XDP_RX_METADATA_VLAN_TAG: Device is capable of exposing receive
* packet VLAN tag via bpf_xdp_metadata_rx_vlan_tag().
* @NETDEV_XDP_RX_METADATA_CHECKSUM: Device is capable of exposing receive
* checksum result via bpf_xdp_metadata_rx_checksum().
*/
enum netdev_xdp_rx_metadata {
NETDEV_XDP_RX_METADATA_TIMESTAMP = 1,
NETDEV_XDP_RX_METADATA_HASH = 2,
NETDEV_XDP_RX_METADATA_VLAN_TAG = 4,
NETDEV_XDP_RX_METADATA_CHECKSUM = 8,
};

/**
Expand Down
28 changes: 28 additions & 0 deletions net/core/xdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,34 @@ __bpf_kfunc int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,
return -EOPNOTSUPP;
}

/**
* bpf_xdp_metadata_rx_checksum - Read XDP frame RX checksum.
* @ctx: XDP context pointer.
* @ip_summed: Return value pointer indicating checksum result.
* @cksum_meta: Return value pointer indicating checksum result metadata.
*
* In case of success, ``ip_summed`` is set to the RX checksum result. Possible
* values are:
* ``XDP_CHECKSUM_NONE``
* ``XDP_CHECKSUM_UNNECESSARY``
* ``XDP_CHECKSUM_COMPLETE``
*
* In case of success, ``cksum_meta`` contains the hw computed checksum value
* for ``XDP_CHECKSUM_COMPLETE`` or the ``csum_level`` for
* ``XDP_CHECKSUM_UNNECESSARY``. It is set to 0 for ``XDP_CHECKSUM_NONE``
*
* Return:
* * Returns 0 on success or ``-errno`` on error.
* * ``-EOPNOTSUPP`` : means device driver does not implement kfunc
* * ``-ENODATA`` : means no RX-timestamp available for this frame
*/
__bpf_kfunc int bpf_xdp_metadata_rx_checksum(const struct xdp_md *ctx,
enum xdp_checksum *ip_summed,
u32 *cksum_meta)
{
return -EOPNOTSUPP;
}

__bpf_kfunc_end_defs();

BTF_KFUNCS_START(xdp_metadata_kfunc_ids)
Expand Down
3 changes: 3 additions & 0 deletions tools/include/uapi/linux/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ enum netdev_xdp_act {
* hash via bpf_xdp_metadata_rx_hash().
* @NETDEV_XDP_RX_METADATA_VLAN_TAG: Device is capable of exposing receive
* packet VLAN tag via bpf_xdp_metadata_rx_vlan_tag().
* @NETDEV_XDP_RX_METADATA_CHECKSUM: Device is capable of exposing receive
* checksum result via bpf_xdp_metadata_rx_checksum().
*/
enum netdev_xdp_rx_metadata {
NETDEV_XDP_RX_METADATA_TIMESTAMP = 1,
NETDEV_XDP_RX_METADATA_HASH = 2,
NETDEV_XDP_RX_METADATA_VLAN_TAG = 4,
NETDEV_XDP_RX_METADATA_CHECKSUM = 8,
};

/**
Expand Down
6 changes: 6 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ static int verify_xsk_metadata(struct xsk *xsk, bool sent_from_af_xdp)
if (!ASSERT_NEQ(meta->rx_hash, 0, "rx_hash"))
return -1;

if (!ASSERT_EQ(meta->ip_summed, XDP_CHECKSUM_NONE, "rx_ip_summed"))
return -1;

if (!ASSERT_EQ(meta->cksum_meta, 0, "rx_cksum_meta"))
return -1;

if (!sent_from_af_xdp) {
if (!ASSERT_NEQ(meta->rx_hash_type & XDP_RSS_TYPE_L4, 0, "rx_hash_type"))
return -1;
Expand Down
8 changes: 8 additions & 0 deletions tools/testing/selftests/bpf/progs/xdp_hw_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ int rx(struct xdp_md *ctx)
else
meta->hint_valid |= XDP_META_FIELD_VLAN_TAG;

err = bpf_xdp_metadata_rx_checksum(ctx,
(enum xdp_checksum *)&meta->ip_summed,
&meta->cksum_meta);
if (err)
meta->rx_cksum_err = err;
else
meta->hint_valid |= XDP_META_FIELD_CHECKSUM;

__sync_add_and_fetch(&pkts_redir, 1);
return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
}
Expand Down
3 changes: 3 additions & 0 deletions tools/testing/selftests/bpf/progs/xdp_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ int rx(struct xdp_md *ctx)
bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash, &meta->rx_hash_type);
bpf_xdp_metadata_rx_vlan_tag(ctx, &meta->rx_vlan_proto,
&meta->rx_vlan_tci);
bpf_xdp_metadata_rx_checksum(ctx,
(enum xdp_checksum *)&meta->ip_summed,
&meta->cksum_meta);

return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
}
Expand Down
Loading
Loading