|
@@ -398,3 +398,42 @@ void xdp_attachment_setup(struct xdp_attachment_info *info,
|
|
|
info->flags = bpf->flags;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(xdp_attachment_setup);
|
|
|
+
|
|
|
+struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
|
|
|
+{
|
|
|
+ unsigned int metasize, headroom, totsize;
|
|
|
+ void *addr, *data_to_copy;
|
|
|
+ struct xdp_frame *xdpf;
|
|
|
+ struct page *page;
|
|
|
+
|
|
|
+ /* Clone into a MEM_TYPE_PAGE_ORDER0 xdp_frame. */
|
|
|
+ metasize = xdp_data_meta_unsupported(xdp) ? 0 :
|
|
|
+ xdp->data - xdp->data_meta;
|
|
|
+ headroom = xdp->data - xdp->data_hard_start;
|
|
|
+ totsize = xdp->data_end - xdp->data + metasize;
|
|
|
+
|
|
|
+ if (sizeof(*xdpf) + totsize > PAGE_SIZE)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ page = dev_alloc_page();
|
|
|
+ if (!page)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ addr = page_to_virt(page);
|
|
|
+ xdpf = addr;
|
|
|
+ memset(xdpf, 0, sizeof(*xdpf));
|
|
|
+
|
|
|
+ addr += sizeof(*xdpf);
|
|
|
+ data_to_copy = metasize ? xdp->data_meta : xdp->data;
|
|
|
+ memcpy(addr, data_to_copy, totsize);
|
|
|
+
|
|
|
+ xdpf->data = addr + metasize;
|
|
|
+ xdpf->len = totsize - metasize;
|
|
|
+ xdpf->headroom = 0;
|
|
|
+ xdpf->metasize = metasize;
|
|
|
+ xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
|
|
|
+
|
|
|
+ xdp_return_buff(xdp);
|
|
|
+ return xdpf;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(xdp_convert_zc_to_xdp_frame);
|