Skip to content

Commit d65a190

Browse files
LorenzoBianconiAlexei Starovoitov
authored andcommitted
net: xdp: add xdp_update_skb_shared_info utility routine
Introduce xdp_update_skb_shared_info routine to update frags array metadata in skb_shared_info data structure converting to a skb from a xdp_buff or xdp_frame. According to the current skb_shared_info architecture in xdp_frame/xdp_buff and to the xdp frags support, there is no need to run skb_add_rx_frag() and reset frags array converting the buffer to a skb since the frag array will be in the same position for xdp_buff/xdp_frame and for the skb, we just need to update memory metadata. Introduce XDP_FLAGS_PF_MEMALLOC flag in xdp_buff_flags in order to mark the xdp_buff or xdp_frame as under memory-pressure if pages of the frags array are under memory pressure. Doing so we can avoid looping over all fragments in xdp_update_skb_shared_info routine. The driver is expected to set the flag constructing the xdp_buffer using xdp_buff_set_frag_pfmemalloc utility routine. Rely on xdp_update_skb_shared_info in __xdp_build_skb_from_frame routine converting the non-linear xdp_frame to a skb after performing a XDP_REDIRECT. Acked-by: Toke Hoiland-Jorgensen <[email protected]> Acked-by: John Fastabend <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Link: https://lore.kernel.org/r/bfd23fb8a8d7438724f7819c567cdf99ffd6226f.1642758637.git.lorenzo@kernel.org Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent d094c98 commit d65a190

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

include/net/xdp.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ struct xdp_txq_info {
6767
};
6868

6969
enum xdp_buff_flags {
70-
XDP_FLAGS_HAS_FRAGS = BIT(0), /* non-linear xdp buff */
70+
XDP_FLAGS_HAS_FRAGS = BIT(0), /* non-linear xdp buff */
71+
XDP_FLAGS_FRAGS_PF_MEMALLOC = BIT(1), /* xdp paged memory is under
72+
* pressure
73+
*/
7174
};
7275

7376
struct xdp_buff {
@@ -96,6 +99,16 @@ static __always_inline void xdp_buff_clear_frags_flag(struct xdp_buff *xdp)
9699
xdp->flags &= ~XDP_FLAGS_HAS_FRAGS;
97100
}
98101

102+
static __always_inline bool xdp_buff_is_frag_pfmemalloc(struct xdp_buff *xdp)
103+
{
104+
return !!(xdp->flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
105+
}
106+
107+
static __always_inline void xdp_buff_set_frag_pfmemalloc(struct xdp_buff *xdp)
108+
{
109+
xdp->flags |= XDP_FLAGS_FRAGS_PF_MEMALLOC;
110+
}
111+
99112
static __always_inline void
100113
xdp_init_buff(struct xdp_buff *xdp, u32 frame_sz, struct xdp_rxq_info *rxq)
101114
{
@@ -151,6 +164,11 @@ static __always_inline bool xdp_frame_has_frags(struct xdp_frame *frame)
151164
return !!(frame->flags & XDP_FLAGS_HAS_FRAGS);
152165
}
153166

167+
static __always_inline bool xdp_frame_is_frag_pfmemalloc(struct xdp_frame *frame)
168+
{
169+
return !!(frame->flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
170+
}
171+
154172
#define XDP_BULK_QUEUE_SIZE 16
155173
struct xdp_frame_bulk {
156174
int count;
@@ -186,6 +204,19 @@ static inline void xdp_scrub_frame(struct xdp_frame *frame)
186204
frame->dev_rx = NULL;
187205
}
188206

207+
static inline void
208+
xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
209+
unsigned int size, unsigned int truesize,
210+
bool pfmemalloc)
211+
{
212+
skb_shinfo(skb)->nr_frags = nr_frags;
213+
214+
skb->len += size;
215+
skb->data_len += size;
216+
skb->truesize += truesize;
217+
skb->pfmemalloc |= pfmemalloc;
218+
}
219+
189220
/* Avoids inlining WARN macro in fast-path */
190221
void xdp_warn(const char *msg, const char *func, const int line);
191222
#define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__)

net/core/xdp.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,14 @@ struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
561561
struct sk_buff *skb,
562562
struct net_device *dev)
563563
{
564+
struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf);
564565
unsigned int headroom, frame_size;
565566
void *hard_start;
567+
u8 nr_frags;
568+
569+
/* xdp frags frame */
570+
if (unlikely(xdp_frame_has_frags(xdpf)))
571+
nr_frags = sinfo->nr_frags;
566572

567573
/* Part of headroom was reserved to xdpf */
568574
headroom = sizeof(*xdpf) + xdpf->headroom;
@@ -582,6 +588,12 @@ struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
582588
if (xdpf->metasize)
583589
skb_metadata_set(skb, xdpf->metasize);
584590

591+
if (unlikely(xdp_frame_has_frags(xdpf)))
592+
xdp_update_skb_shared_info(skb, nr_frags,
593+
sinfo->xdp_frags_size,
594+
nr_frags * xdpf->frame_sz,
595+
xdp_frame_is_frag_pfmemalloc(xdpf));
596+
585597
/* Essential SKB info: protocol and skb->dev */
586598
skb->protocol = eth_type_trans(skb, dev);
587599

0 commit comments

Comments
 (0)