0

In the system I am testing right now, it has a couple of virtual L2 devices chained together to add our own L2.5 headers between Eth headers and IP headers. Now when I use

tcpdump -xx -i vir_device_1

, it actually shows the SLL header with IP header. How do I capture the full packet that is actually going out of the vir_device_1, i.e. after the ndo_start_xmit() device call?

wei
  • 6,629
  • 7
  • 40
  • 52

2 Answers2

1

How do I capture the full packet that is actually going out of the vir_device_1, i.e. after the ndo_start_xmit() device call?

Either by writing your own code to directly use a PF_PACKET/SOCK_RAW socket (you say "SLL header", so this is presumably Linux), or by:

  • making sure you've assigned a special ARPHRD_ value for your virtual interface;
  • using one of the DLT_USERn values for your special set of headers, or asking tcpdump-workers@lists.tcpdump.org for an official DLT_ value to be assigned for them;
  • modifying libpcap to map that ARPHRD_ value to the DLT_ value you're using;
  • modifying tcpdump to handle that DLT_ value;
  • if necessary, modifying other programs that would capture on that interface or read capture files as written by tcpdump on that interface to handle that value as well.

Note that the DLT_USERn values are specifically reserved for private use, and no official versions of libpcap, tcpdump, or Wireshark will ever assign them for their own use (i.e., if you use a DLT_USERn value, don't bother contributing patches to assign that value to your type of headers, as they won't be accepted; other people may already be using it for their own special headers, and that must continue to be supported), so you'll have to maintain the modified versions of libpcap, tcpdump, etc. yourself if you use one of those values rather than getting an official value assigned.

  • Thanks for the answer, I will definitely try both approaches. – wei Jan 18 '13 at 20:22
  • a follow up question, I tried SOCK_RAW/PF_PACKET option. With recvmsg(), I did get the outgoing packet on the interface, now I am wondering how this works? How could a recvmsg() receive an outgoing packet, I mean don't we usually use recvmsg() to receive incoming messages? And when recvmsg() returns a packet, is this packet at the state where it's just been put in this interface's queue or it is about to xmit out of that queue? Thanks. – wei Jan 21 '13 at 06:54
  • PF_PACKET sockets get handed outgoing packets by the packet-transmission code path on Linux. Only the driver knows when the packet's about to be transmitted; the PF_PACKET code doesn't, so outgoing packets are put on the PF_PACKET socket queue at some point before they're transmitted. –  Jan 21 '13 at 20:37
  • Thanks a lot! I have the device driver source code, would it be possible for you to point out some possible callbacks in the driver that I could look for where the packets are put on the PF_PACKET socket queue? Thank you. – wei Jan 21 '13 at 21:08
1

Thanks Guy Harris for providing very helpful answers to my original question!

I am adding this as an answer/note to a follow up question I asked in the comments. Basically my question was what is the status of the packet received by PF_PACKET/SOCK_RAW.

For an software device(no queue), dev_queue_xmit() will call dev_hard_start_xmit(skb, dev) to start transmitting skb buffer. This function calls dev_queue_xmit_nit() before it calls dev->ops->ndo_start_xmit(skb,dev), which means the packet PF_PACKET sees is at the state before any changes made in ndo_start_xmit().

wei
  • 6,629
  • 7
  • 40
  • 52