static struct sk_buff *igc_build_skb(struct igc_ring *rx_ring,
                                     struct igc_rx_buffer *rx_buffer,
-                                    union igc_adv_rx_desc *rx_desc,
-                                    unsigned int size)
+                                    struct xdp_buff *xdp)
 {
-       void *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
+       unsigned int size = xdp->data_end - xdp->data;
        unsigned int truesize = igc_get_rx_frame_truesize(rx_ring, size);
+       unsigned int metasize = xdp->data - xdp->data_meta;
        struct sk_buff *skb;
 
        /* prefetch first cache line of first page */
-       net_prefetch(va);
+       net_prefetch(xdp->data_meta);
 
        /* build an skb around the page buffer */
-       skb = build_skb(va - IGC_SKB_PAD, truesize);
+       skb = build_skb(xdp->data_hard_start, truesize);
        if (unlikely(!skb))
                return NULL;
 
        /* update pointers within the skb to store the data */
-       skb_reserve(skb, IGC_SKB_PAD);
+       skb_reserve(skb, xdp->data - xdp->data_hard_start);
        __skb_put(skb, size);
+       if (metasize)
+               skb_metadata_set(skb, metasize);
 
        igc_rx_buffer_flip(rx_buffer, truesize);
        return skb;
                                         struct xdp_buff *xdp,
                                         ktime_t timestamp)
 {
+       unsigned int metasize = xdp->data - xdp->data_meta;
        unsigned int size = xdp->data_end - xdp->data;
        unsigned int truesize = igc_get_rx_frame_truesize(rx_ring, size);
        void *va = xdp->data;
        struct sk_buff *skb;
 
        /* prefetch first cache line of first page */
-       net_prefetch(va);
+       net_prefetch(xdp->data_meta);
 
        /* allocate a skb to store the frags */
-       skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGC_RX_HDR_LEN);
+       skb = napi_alloc_skb(&rx_ring->q_vector->napi,
+                            IGC_RX_HDR_LEN + metasize);
        if (unlikely(!skb))
                return NULL;
 
                headlen = eth_get_headlen(skb->dev, va, IGC_RX_HDR_LEN);
 
        /* align pull length to size of long to optimize memcpy performance */
-       memcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long)));
+       memcpy(__skb_put(skb, headlen + metasize), xdp->data_meta,
+              ALIGN(headlen + metasize, sizeof(long)));
+
+       if (metasize) {
+               skb_metadata_set(skb, metasize);
+               __skb_pull(skb, metasize);
+       }
 
        /* update all of the pointers */
        size -= headlen;
                if (!skb) {
                        xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq);
                        xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring),
-                                        igc_rx_offset(rx_ring) + pkt_offset, size, false);
+                                        igc_rx_offset(rx_ring) + pkt_offset,
+                                        size, true);
 
                        skb = igc_xdp_run_prog(adapter, &xdp);
                }
                } else if (skb)
                        igc_add_rx_frag(rx_ring, rx_buffer, skb, size);
                else if (ring_uses_build_skb(rx_ring))
-                       skb = igc_build_skb(rx_ring, rx_buffer, rx_desc, size);
+                       skb = igc_build_skb(rx_ring, rx_buffer, &xdp);
                else
                        skb = igc_construct_skb(rx_ring, rx_buffer, &xdp,
                                                timestamp);