title: Extracting data from struct sk_buff
body: <p>I'm attempting to extract data from a <code>struct sk_buff</code>, but have not received the output I am expecting. The frame in question is 34 bytes; a 14-byte Ethernet header wrapped around an 8-byte (experimental protocol) header:</p>
  
  <pre><code>struct monitoring_hdr {
      u8      version;
      u8      type;
      u8      reserved;
      u8      haddr_len;
  
      u32     clock;
  } __packed;
  </code></pre>
  
  <p>After this header, there are two, variable-length hardware addresses (their lengths are dictated by the <code>haddr_len</code> field above). In the example here, they are both 6 bytes long.</p>
  
  <p>The following code extracts the header (the struct) correctly, but not the two MAC addresses that follow.</p>
  
  <p><strong>Sender side:</strong></p>
  
  <pre><code>    ...
      skb = alloc_skb(mtu, GFP_ATOMIC);
      if (unlikely(!skb))
              return;
      skb_reserve(skb, ll_hlen);
      skb_reset_network_header(skb);
      nwp = (struct monitoring_hdr *)skb_put(skb, hdr_len);
      /* ... Set up fields in struct monitoring_hdr ... */
      memcpy(skb_put(skb, dev-&gt;addr_len), src, dev-&gt;addr_len);
      memcpy(skb_put(skb, dev-&gt;addr_len), dst, dev-&gt;addr_len);
      ...
  </code></pre>
  
  <p><strong>Receiver side:</strong></p>
  
  <pre><code>   ...
     skb_reset_network_header(skb);
     nwp = (struct monitoring_hdr *)skb_network_header(skb);
  
     src = skb_pull(skb, nwp-&gt;haddr_len);
     dst = skb_pull(skb, nwp-&gt;haddr_len);
     ...
  </code></pre>
  
  <p><strong>Expected output:</strong></p>
  
  <p>I used tcpdump to capture the packet in question on the wire, and saw this (it was actually padded to 60 bytes by the sender's NIC, which I've omitted):</p>
  
  <pre><code>0000 | 00 90 f5 c6 44 5b 00 0e  c6 89 04 2f c0 df 01 03
  0010 | 00 06 d0 ba 8c 88 00 0e  c6 89 04 2f 00 90 f5 c6
  0020 | 44 5b
  </code></pre>
  
  <p>The first 14 bytes is the Ethernet header. The following 8 bytes (starting with <code>01</code> and ending with <code>88</code>) should be the bytes put into the <code>struct monitoring_hdr</code>, which executes correctly. Then, I am expecting the following MAC addresses to be found:</p>
  
  <pre><code>src = 00 0e c6 89 04 2f
  dst = 00 90 f5 c6 44 5b
  </code></pre>
  
  <p><strong>Actual output:</strong></p>
  
  <p>However, the data that I receive is shifted two bytes to the left:</p>
  
  <pre><code>src = 8c 88 00 0e c6 89
  dst = 04 2f 00 90 f5 c6
  </code></pre>
  
  <p>Can anyone see a logical flaw in above code? Or is there a better way to do this? I've also tried <code>skb_pull</code> in place of <code>skb_network_header</code> on the receiving side, but that resulted in a kernel panic.</p>
  
  <p>Thanks in advance for any help.</p>
  
  <p><strong>SOLUTION</strong>:</p>
  
  <p>The pointer to the first byte of the data in the <code>sk_buff</code> was not being pointed to by <code>src</code> as it should have been. I ended up using the following:</p>
  
  <pre><code>   ...
     skb_reset_network_header(skb);
     nwp = (struct monitoring_hdr *)skb_network_header(skb);
     skb_pull(skb, offsetof(struct monitoring_hdr, haddrs_begin));
  
     src = skb-&gt;data;
     dst = skb_pull(skb, nwp-&gt;haddr_len);
     ...
  </code></pre>