I wish I were a little late. I had the same problem, and unfortunately, the use of PACKET_TX_RING is not well documented. But, fortunately, it is still fairly easy to understand using a related program.
First you need tshark (or wirehark) and the source packet_mm from the link you posted. An example source fills the buffer from 0 to 150 and then sends it directly to this device. Using tshark, we read what is sent.
Run tshark in one shell (by clicking on the loopback device):
$ tshark -V -i lo
and run package_mm in another shell:
$ packet_mm lo
Check one frame:
Frame 1 (150 bytes on wire, 150 bytes captured) Arrival Time: Nov 12, 2011 13:07:02.636424000 [Time delta from previous captured frame: 0.000005000 seconds] [Time delta from previous displayed frame: 0.000005000 seconds] [Time since reference or first frame: 337.280499000 seconds] Frame Number: 1001 Frame Length: 150 bytes Capture Length: 150 bytes [Frame is marked: False] [Protocols in frame: eth:data] Ethernet II, Src: 06:07:08:09:0a:0b (06:07:08:09:0a:0b), Dst: 3com_03:04:05 (00:01:02:03:04:05) Destination: 3com_03:04:05 (00:01:02:03:04:05) Address: 3com_03:04:05 (00:01:02:03:04:05) .... ...0 .... .... .... .... = IG bit: Individual address (unicast) .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) Source: 06:07:08:09:0a:0b (06:07:08:09:0a:0b) Address: 06:07:08:09:0a:0b (06:07:08:09:0a:0b) .... ...0 .... .... .... .... = IG bit: Individual address (unicast) .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default) Type: Unknown (0x0c0d) Data (136 bytes) 0000 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d ................ 0010 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d .. !"#$%&'()*+,- 0020 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d ./0123456789:;<= 0030 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d > ?@ABCDEFGHIJKLM 0040 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d NOPQRSTUVWXYZ[\] 0050 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d ^_`abcdefghijklm 0060 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d nopqrstuvwxyz{|} 0070 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d ~............... 0080 8e 8f 90 91 92 93 94 95 ........ Data: 0E0F101112131415161718191A1B1C1D1E1F202122232425... [Length: 136]
The destination MAC address is 00: 01: 02: 03: 04: 05 and the source MAC is 06: 07: 08: 09: 0a: 0b. And start the data (immediately after the Ethernet header) using 0x0e (14).
So, an approximate program data offset is the beginning of the packet being sent (ethernet).
So, this is really the right way to fill the buffer for sending (make sure pktlen is not larger than the size of your frame):
// fill data off = ((uint8_t *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll)); memcpy(off, pkt, pktlen);
And no data will be overwritten. But you must provide the Ethernet, IP and UDP header yourself.
EDIT: For TX_Ring, the frame structure is as follows:
- Start The frame should be aligned using TPACKET_ALIGNMENT = 16
- struct tpacket_hdr (size = 32 bytes)
- pad for TPACKET_ALIGNMENT = 16 (so the fill size is 0)
- packet data
- Pad to align to TPACKET_ALIGNMENT = 16 (so the next frame is aligned 16 bits)