[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <a31b2599948c8d8679c6454b9191e70c1c732c32.1616179034.git.lorenzo@kernel.org>
Date: Fri, 19 Mar 2021 22:47:24 +0100
From: Lorenzo Bianconi <lorenzo@...nel.org>
To: bpf@...r.kernel.org, netdev@...r.kernel.org
Cc: lorenzo.bianconi@...hat.com, davem@...emloft.net, kuba@...nel.org,
ast@...nel.org, daniel@...earbox.net, shayagr@...zon.com,
john.fastabend@...il.com, dsahern@...nel.org, brouer@...hat.com,
echaudro@...hat.com, jasowang@...hat.com,
alexander.duyck@...il.com, saeed@...nel.org,
maciej.fijalkowski@...el.com, sameehj@...zon.com
Subject: [PATCH v7 bpf-next 10/14] bpf: add new frame_length field to the XDP ctx
From: Eelco Chaudron <echaudro@...hat.com>
This patch adds a new field to the XDP context called frame_length,
which will hold the full length of the packet, including fragments
if existing.
eBPF programs can determine if fragments are present using something
like:
if (ctx->data_end - ctx->data < ctx->frame_length) {
/* Fragements exists. /*
}
Signed-off-by: Eelco Chaudron <echaudro@...hat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@...nel.org>
---
include/linux/filter.h | 7 +++++++
include/net/xdp.h | 12 ++++++++++++
include/uapi/linux/bpf.h | 1 +
net/core/filter.c | 8 ++++++++
net/core/xdp.c | 1 +
tools/include/uapi/linux/bpf.h | 1 +
6 files changed, 30 insertions(+)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index b2b85b2cad8e..511d812fd18c 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -768,6 +768,13 @@ static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
* already takes rcu_read_lock() when fetching the program, so
* it's not necessary here anymore.
*/
+ xdp->frame_length = xdp->data_end - xdp->data;
+ if (unlikely(xdp->mb)) {
+ struct xdp_shared_info *xdp_sinfo;
+
+ xdp_sinfo = xdp_get_shared_info_from_buff(xdp);
+ xdp->frame_length += xdp_sinfo->data_length;
+ }
return __BPF_PROG_RUN(prog, xdp, BPF_DISPATCHER_FUNC(xdp));
}
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 19cd6642e087..e47d9e8da547 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -75,6 +75,10 @@ struct xdp_buff {
struct xdp_txq_info *txq;
u32 frame_sz:31; /* frame size to deduce data_hard_end/reserved tailroom*/
u32 mb:1; /* xdp non-linear buffer */
+ u32 frame_length; /* Total frame length across all buffers. Only needs
+ * to be updated by helper functions, as it will be
+ * initialized at XDP program start.
+ */
};
static __always_inline void
@@ -235,6 +239,14 @@ void xdp_convert_frame_to_buff(struct xdp_frame *frame, struct xdp_buff *xdp)
xdp->data_meta = frame->data - frame->metasize;
xdp->frame_sz = frame->frame_sz;
xdp->mb = frame->mb;
+ xdp->frame_length = frame->len;
+
+ if (unlikely(xdp->mb)) {
+ struct xdp_shared_info *xdp_sinfo;
+
+ xdp_sinfo = xdp_get_shared_info_from_buff(xdp);
+ xdp->frame_length += xdp_sinfo->data_length;
+ }
}
static inline
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 2d3036e292a9..4dcc5ad736b4 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5213,6 +5213,7 @@ struct xdp_md {
__u32 rx_queue_index; /* rxq->queue_index */
__u32 egress_ifindex; /* txq->dev->ifindex */
+ __u32 frame_length;
};
/* DEVMAP map-value layout
diff --git a/net/core/filter.c b/net/core/filter.c
index a607ea8321bd..b047757bd839 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3873,6 +3873,7 @@ static int bpf_xdp_mb_adjust_tail(struct xdp_buff *xdp, int offset)
memset(xdp_get_frag_address(frag) + size, 0, offset);
xdp_set_frag_size(frag, size + offset);
xdp_sinfo->data_length += offset;
+ xdp->frame_length += offset;
} else {
int i, frags_to_free = 0;
@@ -3894,6 +3895,7 @@ static int bpf_xdp_mb_adjust_tail(struct xdp_buff *xdp, int offset)
* to adjust the data_length in line.
*/
xdp_sinfo->data_length -= shrink;
+ xdp->frame_length -= shrink;
xdp_set_frag_size(frag, size - shrink);
break;
}
@@ -9126,6 +9128,12 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
offsetof(struct net_device, ifindex));
break;
+ case offsetof(struct xdp_md, frame_length):
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_buff,
+ frame_length),
+ si->dst_reg, si->src_reg,
+ offsetof(struct xdp_buff, frame_length));
+ break;
}
return insn - insn_buf;
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 7388bc6d680b..fb7d0724a5b6 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -510,6 +510,7 @@ void xdp_return_num_frags_from_buff(struct xdp_buff *xdp, u16 num_frags)
struct page *page = xdp_get_frag_page(frag);
xdp_sinfo->data_length -= xdp_get_frag_size(frag);
+ xdp->frame_length -= xdp_get_frag_size(frag);
__xdp_return(page_address(page), &xdp->rxq->mem, false, NULL);
}
xdp_sinfo->nr_frags -= num_frags;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 2d3036e292a9..4dcc5ad736b4 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5213,6 +5213,7 @@ struct xdp_md {
__u32 rx_queue_index; /* rxq->queue_index */
__u32 egress_ifindex; /* txq->dev->ifindex */
+ __u32 frame_length;
};
/* DEVMAP map-value layout
--
2.30.2
Powered by blists - more mailing lists