From: Jonathan Lemon <b...@fb.com> skb_zcopy() flag indicates whether the skb has a zerocopy ubuf. netgpu does not use ubufs, so skb_zdata() indicates whether the skb is carrying zero copy data, and should be left alone, while skb_zcopy() indicates whether there is an attached ubuf.
Signed-off-by: Jonathan Lemon <jonathan.le...@gmail.com> --- include/linux/skbuff.h | 24 +++++++++++++++++++++++- net/core/skbuff.c | 17 ++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 006e10fcc7d9..017c20792c23 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -443,8 +443,12 @@ enum { /* generate software time stamp when entering packet scheduling */ SKBTX_SCHED_TSTAMP = 1 << 6, + + /* fragments are accessed only via DMA */ + SKBTX_DEV_NETDMA = 1 << 7, }; +#define SKBTX_ZERODATA_FRAG (SKBTX_DEV_ZEROCOPY | SKBTX_DEV_NETDMA) #define SKBTX_ZEROCOPY_FRAG (SKBTX_DEV_ZEROCOPY | SKBTX_SHARED_FRAG) #define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \ SKBTX_SCHED_TSTAMP) @@ -1420,6 +1424,24 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) return &skb_shinfo(skb)->hwtstamps; } +static inline bool skb_netdma(struct sk_buff *skb) +{ + return skb && skb_shinfo(skb)->tx_flags & SKBTX_DEV_NETDMA; +} + +static inline bool skb_zdata(struct sk_buff *skb) +{ + return skb && skb_shinfo(skb)->tx_flags & SKBTX_ZERODATA_FRAG; +} + +static inline void skb_netdma_set(struct sk_buff *skb, void *arg) +{ + if (skb && arg) { + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_NETDMA; + skb_shinfo(skb)->destructor_arg = arg; + } +} + static inline struct ubuf_info *skb_zcopy(struct sk_buff *skb) { bool is_zcopy = skb && skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY; @@ -3264,7 +3286,7 @@ static inline int skb_add_data(struct sk_buff *skb, static inline bool skb_can_coalesce(struct sk_buff *skb, int i, const struct page *page, int off) { - if (skb_zcopy(skb)) + if (skb_zdata(skb)) return false; if (i) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2a391042be53..1422b99b7090 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -69,6 +69,7 @@ #include <net/xfrm.h> #include <net/mpls.h> #include <net/mptcp.h> +#include <net/netgpu.h> #include <linux/uaccess.h> #include <trace/events/skb.h> @@ -1300,6 +1301,8 @@ int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb, } skb_zcopy_set(skb, uarg, NULL); + skb_netdma_set(skb, sk->sk_user_data); + return skb->len - orig_len; } EXPORT_SYMBOL_GPL(skb_zerocopy_iter_stream); @@ -1307,6 +1310,16 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_iter_stream); static int skb_zerocopy_clone(struct sk_buff *nskb, struct sk_buff *orig, gfp_t gfp_mask) { + if (skb_netdma(orig)) { + if (skb_netdma(nskb)) { + WARN_ONCE(1, "zc clone, dst skb is set\n"); + if (skb_uarg(nskb) != skb_uarg(orig)) + return -EIO; + } + skb_netdma_set(nskb, skb_shinfo(orig)->destructor_arg); + return 0; + } + if (skb_zcopy(orig)) { if (skb_zcopy(nskb)) { /* !gfp_mask callers are verified to !skb_zcopy(nskb) */ @@ -2055,6 +2068,8 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta) */ int i, k, eat = (skb->tail + delta) - skb->end; + BUG_ON(skb_netdma(skb)); + if (eat > 0 || skb_cloned(skb)) { if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0, GFP_ATOMIC)) @@ -3305,7 +3320,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) if (skb_headlen(skb)) return 0; - if (skb_zcopy(tgt) || skb_zcopy(skb)) + if (skb_zdata(tgt) || skb_zdata(skb)) return 0; todo = shiftlen; -- 2.24.1