igc: Add XDP hints kfuncs for RX timestamp
authorJesper Dangaard Brouer <brouer@redhat.com>
Tue, 18 Apr 2023 13:30:57 +0000 (15:30 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 27 Apr 2023 16:42:19 +0000 (18:42 +0200)
The NIC hardware RX timestamping mechanism adds an optional tailored
header before the MAC header containing packet reception time. Optional
depending on RX descriptor TSIP status bit (IGC_RXDADV_STAT_TSIP). In
case this bit is set driver does offset adjustments to packet data start
and extracts the timestamp.

The timestamp need to be extracted before invoking the XDP bpf_prog,
because this area just before the packet is also accessible by XDP via
data_meta context pointer (and helper bpf_xdp_adjust_meta). Thus, an XDP
bpf_prog can potentially overwrite this and corrupt data that we want to
extract with the new kfunc for reading the timestamp.

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Song Yoong Siang <yoong.siang.song@intel.com>
Link: https://lore.kernel.org/bpf/168182465791.616355.2583922957423587914.stgit@firesoul
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_main.c

index c609a2e648f8ef67588400abcb0a2fc4a6f38cea..18d4af934d8caad711173a1087898c52d22edaef 100644 (file)
@@ -503,6 +503,7 @@ struct igc_rx_buffer {
 struct igc_xdp_buff {
        struct xdp_buff xdp;
        union igc_adv_rx_desc *rx_desc;
+       ktime_t rx_ts; /* data indication bit IGC_RXDADV_STAT_TSIP */
 };
 
 struct igc_q_vector {
index c18486f46085155f4f1e80563c1d473693b9ac6f..b78e0e6562c82307e957910d5cd9f8f2bc371895 100644 (file)
@@ -2549,6 +2549,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
                if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) {
                        timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
                                                        pktbuf);
+                       ctx.rx_ts = timestamp;
                        pkt_offset = IGC_TS_HDR_LEN;
                        size -= IGC_TS_HDR_LEN;
                }
@@ -2737,6 +2738,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
                if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) {
                        timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
                                                        bi->xdp->data);
+                       ctx->rx_ts = timestamp;
 
                        bi->xdp->data += IGC_TS_HDR_LEN;
 
@@ -6523,8 +6525,22 @@ static int igc_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash,
        return 0;
 }
 
+static int igc_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp)
+{
+       const struct igc_xdp_buff *ctx = (void *)_ctx;
+
+       if (igc_test_staterr(ctx->rx_desc, IGC_RXDADV_STAT_TSIP)) {
+               *timestamp = ctx->rx_ts;
+
+               return 0;
+       }
+
+       return -ENODATA;
+}
+
 static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
        .xmo_rx_hash                    = igc_xdp_rx_hash,
+       .xmo_rx_timestamp               = igc_xdp_rx_timestamp,
 };
 
 /**