title: PACKET_MMAP data offset
body: <p>I am writing the code to send an UDP packet using PACKET_TX_RING ring, and I don't understand the example code described here:
  <a href="http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap#Kernel_Patch" rel="nofollow">http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap#Kernel_Patch</a></p>
  
  <p>The /usr/src/linux/Documentation/networking/packet_mmap.txt
  says that the frame structure is this:</p>
  
  <p>/*
     Frame structure:</p>
  
  <ul>
  <li>Start. Frame must be aligned to TPACKET_ALIGNMENT=16</li>
  <li>struct tpacket_hdr</li>
  <li>pad to TPACKET_ALIGNMENT=16</li>
  <li>struct sockaddr_ll</li>
  <li>Gap, chosen so that packet data (Start+tp_net) aligns to
   TPACKET_ALIGNMENT=16</li>
  <li>Start+tp_mac: [ Optional MAC header ]</li>
  <li>Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.</li>
  <li><p>Pad to align to TPACKET_ALIGNMENT=16</p>
  
  <p>*/</p></li>
  </ul>
  
  <p>If data starts at Start + tp_net, then why the code in the example substracts sizeof(struct sockaddr_ll) instead of summing it, this is the line:</p>
  
  <pre><code>/* get data offset */
          data_offset = TPACKET_HDRLEN - sizeof(struct sockaddr_ll);
  printf("data offset = %d bytes\n", data_offset);
  </code></pre>
  
  <p>After calculating the pointer to packet data, the data is copied:</p>
  
  <pre><code>  // fill data
    off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll));
    memcpy(off, pkt, pktlen);
  </code></pre>
  
  <p>Tis looks like data corruption to me, the socket address and optional mac address will be overwriten by the data to transmit. In my case, if I use this code, the UDP packet header will be overwritten, is this correct?</p>
  
  <p>Thanks in advance</p>