8383#include <net/netfilter/nf_conntrack_bpf.h>
8484#include <net/netkit.h>
8585#include <linux/un.h>
86+ #include <net/xdp_sock_drv.h>
8687
8788#include "dev.h"
8889
@@ -4096,6 +4097,40 @@ static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset)
40964097 return 0 ;
40974098}
40984099
4100+ static void bpf_xdp_shrink_data_zc (struct xdp_buff * xdp , int shrink ,
4101+ struct xdp_mem_info * mem_info , bool release )
4102+ {
4103+ struct xdp_buff * zc_frag = xsk_buff_get_tail (xdp );
4104+
4105+ if (release ) {
4106+ xsk_buff_del_tail (zc_frag );
4107+ __xdp_return (NULL , mem_info , false, zc_frag );
4108+ } else {
4109+ zc_frag -> data_end -= shrink ;
4110+ }
4111+ }
4112+
4113+ static bool bpf_xdp_shrink_data (struct xdp_buff * xdp , skb_frag_t * frag ,
4114+ int shrink )
4115+ {
4116+ struct xdp_mem_info * mem_info = & xdp -> rxq -> mem ;
4117+ bool release = skb_frag_size (frag ) == shrink ;
4118+
4119+ if (mem_info -> type == MEM_TYPE_XSK_BUFF_POOL ) {
4120+ bpf_xdp_shrink_data_zc (xdp , shrink , mem_info , release );
4121+ goto out ;
4122+ }
4123+
4124+ if (release ) {
4125+ struct page * page = skb_frag_page (frag );
4126+
4127+ __xdp_return (page_address (page ), mem_info , false, NULL );
4128+ }
4129+
4130+ out :
4131+ return release ;
4132+ }
4133+
40994134static int bpf_xdp_frags_shrink_tail (struct xdp_buff * xdp , int offset )
41004135{
41014136 struct skb_shared_info * sinfo = xdp_get_shared_info_from_buff (xdp );
@@ -4110,12 +4145,7 @@ static int bpf_xdp_frags_shrink_tail(struct xdp_buff *xdp, int offset)
41104145
41114146 len_free += shrink ;
41124147 offset -= shrink ;
4113-
4114- if (skb_frag_size (frag ) == shrink ) {
4115- struct page * page = skb_frag_page (frag );
4116-
4117- __xdp_return (page_address (page ), & xdp -> rxq -> mem ,
4118- false, NULL );
4148+ if (bpf_xdp_shrink_data (xdp , frag , shrink )) {
41194149 n_frags_free ++ ;
41204150 } else {
41214151 skb_frag_size_sub (frag , shrink );
0 commit comments