mirror of
https://github.com/torvalds/linux.git
synced 2026-05-05 23:05:25 -04:00
idpf: export RX hardware timestamping information to XDP
The logic is similar to idpf_rx_hwtstamp, but the data is exported as a BPF kfunc instead of appended to an skb to support grabbing timestamps in xsk packets. A idpf_queue_has(PTP, rxq) condition is added to check the queue supports PTP similar to idpf_rx_process_skb_fields. Tested using an xsk connection and checking xdp timestamps are retrievable in received packets. Cc: intel-wired-lan@lists.osuosl.org Signed-off-by: YiFei Zhu <zhuyifei@google.com> Signed-off-by: Mina Almasry <almasrymina@google.com> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
/* Copyright (C) 2025 Intel Corporation */
|
||||
|
||||
#include "idpf.h"
|
||||
#include "idpf_ptp.h"
|
||||
#include "idpf_virtchnl.h"
|
||||
#include "xdp.h"
|
||||
#include "xsk.h"
|
||||
@@ -398,8 +399,38 @@ static int idpf_xdpmo_rx_hash(const struct xdp_md *ctx, u32 *hash,
|
||||
pt);
|
||||
}
|
||||
|
||||
static int idpf_xdpmo_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
|
||||
{
|
||||
const struct libeth_xdp_buff *xdp = (typeof(xdp))ctx;
|
||||
struct idpf_xdp_rx_desc desc __uninitialized;
|
||||
const struct idpf_rx_queue *rxq;
|
||||
u64 cached_time, ts_ns;
|
||||
u32 ts_high;
|
||||
|
||||
rxq = libeth_xdp_buff_to_rq(xdp, typeof(*rxq), xdp_rxq);
|
||||
|
||||
if (!idpf_queue_has(PTP, rxq))
|
||||
return -ENODATA;
|
||||
|
||||
idpf_xdp_get_qw1(&desc, xdp->desc);
|
||||
|
||||
if (!(idpf_xdp_rx_ts_low(&desc) & VIRTCHNL2_RX_FLEX_TSTAMP_VALID))
|
||||
return -ENODATA;
|
||||
|
||||
cached_time = READ_ONCE(rxq->cached_phc_time);
|
||||
|
||||
idpf_xdp_get_qw3(&desc, xdp->desc);
|
||||
|
||||
ts_high = idpf_xdp_rx_ts_high(&desc);
|
||||
ts_ns = idpf_ptp_tstamp_extend_32b_to_64b(cached_time, ts_high);
|
||||
|
||||
*timestamp = ts_ns;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xdp_metadata_ops idpf_xdpmo = {
|
||||
.xmo_rx_hash = idpf_xdpmo_rx_hash,
|
||||
.xmo_rx_timestamp = idpf_xdpmo_rx_timestamp,
|
||||
};
|
||||
|
||||
void idpf_xdp_set_features(const struct idpf_vport *vport)
|
||||
|
||||
@@ -112,11 +112,13 @@ struct idpf_xdp_rx_desc {
|
||||
aligned_u64 qw1;
|
||||
#define IDPF_XDP_RX_BUF GENMASK_ULL(47, 32)
|
||||
#define IDPF_XDP_RX_EOP BIT_ULL(1)
|
||||
#define IDPF_XDP_RX_TS_LOW GENMASK_ULL(31, 24)
|
||||
|
||||
aligned_u64 qw2;
|
||||
#define IDPF_XDP_RX_HASH GENMASK_ULL(31, 0)
|
||||
|
||||
aligned_u64 qw3;
|
||||
#define IDPF_XDP_RX_TS_HIGH GENMASK_ULL(63, 32)
|
||||
} __aligned(4 * sizeof(u64));
|
||||
static_assert(sizeof(struct idpf_xdp_rx_desc) ==
|
||||
sizeof(struct virtchnl2_rx_flex_desc_adv_nic_3));
|
||||
@@ -128,6 +130,8 @@ static_assert(sizeof(struct idpf_xdp_rx_desc) ==
|
||||
#define idpf_xdp_rx_buf(desc) FIELD_GET(IDPF_XDP_RX_BUF, (desc)->qw1)
|
||||
#define idpf_xdp_rx_eop(desc) !!((desc)->qw1 & IDPF_XDP_RX_EOP)
|
||||
#define idpf_xdp_rx_hash(desc) FIELD_GET(IDPF_XDP_RX_HASH, (desc)->qw2)
|
||||
#define idpf_xdp_rx_ts_low(desc) FIELD_GET(IDPF_XDP_RX_TS_LOW, (desc)->qw1)
|
||||
#define idpf_xdp_rx_ts_high(desc) FIELD_GET(IDPF_XDP_RX_TS_HIGH, (desc)->qw3)
|
||||
|
||||
static inline void
|
||||
idpf_xdp_get_qw0(struct idpf_xdp_rx_desc *desc,
|
||||
@@ -149,6 +153,9 @@ idpf_xdp_get_qw1(struct idpf_xdp_rx_desc *desc,
|
||||
desc->qw1 = ((const typeof(desc))rxd)->qw1;
|
||||
#else
|
||||
desc->qw1 = ((u64)le16_to_cpu(rxd->buf_id) << 32) |
|
||||
((u64)rxd->ts_low << 24) |
|
||||
((u64)rxd->fflags1 << 16) |
|
||||
((u64)rxd->status_err1 << 8) |
|
||||
rxd->status_err0_qw1;
|
||||
#endif
|
||||
}
|
||||
@@ -166,6 +173,19 @@ idpf_xdp_get_qw2(struct idpf_xdp_rx_desc *desc,
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
idpf_xdp_get_qw3(struct idpf_xdp_rx_desc *desc,
|
||||
const struct virtchnl2_rx_flex_desc_adv_nic_3 *rxd)
|
||||
{
|
||||
#ifdef __LIBETH_WORD_ACCESS
|
||||
desc->qw3 = ((const typeof(desc))rxd)->qw3;
|
||||
#else
|
||||
desc->qw3 = ((u64)le32_to_cpu(rxd->ts_high) << 32) |
|
||||
((u64)le16_to_cpu(rxd->fmd6) << 16) |
|
||||
le16_to_cpu(rxd->l2tag1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void idpf_xdp_set_features(const struct idpf_vport *vport);
|
||||
|
||||
int idpf_xdp(struct net_device *dev, struct netdev_bpf *xdp);
|
||||
|
||||
Reference in New Issue
Block a user