2011-10-14 33 views
4

我写的代码使用PACKET_TX_RING环发送一个UDP包,我不明白这里所描述的示例代码: http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap#Kernel_PatchPACKET_MMAP数据偏移

在/ usr/src/linux目录/文件/网络/ packet_mmap.txt 说,框架结构是这样的:

/* 帧结构:

  • 开始。帧必须对齐到TPACKET_ALIGNMENT = 16
  • 结构tpacket_hdr
  • 垫TPACKET_ALIGNMENT = 16
  • 结构sockaddr_ll
  • 峡,选择为使得分组数据(START + tp_net)对齐到 TPACKET_ALIGNMENT = 16
  • 开始+ tp_mac:[可选MAC头]
  • 开始+ tp_net:数据包数据,与TPACKET_ALIGNMENT = 16对齐。
  • 垫。如果数据开始于开始+ tp_net,对准TPACKET_ALIGNMENT = 16

    */

然后为什么在示例substracts的sizeof代码(结构sockaddr_ll)代替求和它,这是行:

/* get data offset */ 
     data_offset = TPACKET_HDRLEN - sizeof(struct sockaddr_ll); 
printf("data offset = %d bytes\n", data_offset); 

计算指针的分组数据后,将数据复制:

// fill data 
    off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll)); 
    memcpy(off, pkt, pktlen); 

Tis看起来像是我的数据损坏,套接字地址和可选的mac地址将被要覆盖的数据传输。在我的情况下,如果我使用这个代码,UDP数据包头将被覆盖,这是正确的吗?

在此先感谢

回答

3

对不起,我有点晚。 我有一个非常相同的问题,不幸的是使用PACKET_TX_RING没有很好的记录。但幸运的是,使用链接的示例程序很容易。

首先,您需要tshark(或wireshark)和您发布的链接中的packet_mm源。示例源用0到150填充缓冲区,然后直接将其发送到给定设备。使用tshark我们会读出发送的内容。

在一个壳运行tshark的(攻丝回环设备):

$ tshark -V -i lo 

和运行packet_mm在另一个壳:

$ packet_mm lo 

退房一个帧:

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 ./:;<= 
0030 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d >[email protected] 
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] 

的目标MAC地址为00:01:02:03:04:05和源MAC地址为06:07:08:09:0a:0b。 和0x0e(14)数据开始(在以太网报头之后)。

因此,示例程序的数据偏移量是要发送的(以太网)数据包的开始。

所以这确实是正确的方法来填充缓冲区发送(确保PKTLEN是不是比你的帧大小):

// fill data 
off = ((uint8_t *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll)); 
memcpy(off, pkt, pktlen); 

,没有数据将被覆盖。但是你必须自己提供以太网,IP和UDP头。

编辑: 对于TX_Ring,框架结构似乎是:

  • 开始。帧必须对齐到TPACKET_ALIGNMENT = 16
  • 结构tpacket_hdr(大小= 32个字节)
  • 垫TPACKET_ALIGNMENT = 16(因此有效地填充大小为0)
  • 分组数据
  • 垫对齐到TPACKET_ALIGNMENT = 16 (所以下一帧是16Bit对齐的)