Search code examples
clinux-kernellinux-device-driverpacketskb

How to extract entire packet from skb including ethernet header, ip, and tcp plus pay load in poll method of device driver


in r8169 driver from realtek it does

    rx_buf = page_address(tp->Rx_databuff[entry]);
    dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
    prefetch(rx_buf);
    skb_copy_to_linear_data(skb, rx_buf, pkt_size);<----//Do I get packet at this????
    skb->tail += pkt_size;
    skb->len = pkt_size;
    dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
    //csum...
    skb->protocol = eth_type_trans(skb, dev);
    napi_gro_receive(&tp->napi, skb);

this is inside rtl_rx function called from poll of driver. I like to know in above code how can I extract the entire packet from skb at which line afterwards.

I assume at this line

             skb_copy_to_linear_data(skb, rx_buf, pkt_size);

I should have a packet, but like to know the correct way I can create a kmalloc obect like

         void   *packet=   kmalloc(....sizeof(struct ethhdr)+sizeof(struct iphdr)+sizeof(tcphdr))

and read ethernet ip and tcp headers from void *packet

How to achieve it

Or should I simple do skb_netword_header, skb_tcp_header, etc... to extract the headers and payload from skb after it get populated in above lines,

or can I simply cast as

              rx_buf = page_address(tp->Rx_databuff[entry]);
              struct ether_header ethhdr_of_packet=(struct eher_header *) rx_buf;

Should it work?


Solution

  • The highlighted line (the one with skb_copy_to_linear_data()) indeed copies entire packet data from the buffer in the driver-internal Rx ring (rx_buf) to the data buffer of the skb.

    static inline void skb_copy_to_linear_data(struct sk_buff *skb,
                           const void *from,
                           const unsigned int len)
    {
        memcpy(skb->data, from, len);
    }
    

    Casting the rx_buf pointer to Ethernet header should be OK, too. However, the purpose of accessing the packet header like this is rather vague in the question of yours. Are you trying to just print ("dump") the packet or do you intend to copy the packet data to a completely different buffer to be consumed elsewhere?