Смещение данных PACKET_MMAP - PullRequest
       16

Смещение данных PACKET_MMAP

4 голосов
/ 14 октября 2011

Я пишу код для отправки пакета UDP, используя кольцо PACKET_TX_RING, и я не понимаю пример кода, описанного здесь: http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap#Kernel_Patch

/usr/src/linux/Documentation/networking/packet_mmap.txt говорит, что структура кадра такова:

/ * Рамная конструкция:

  • Start. Кадр должен быть выровнен по TPACKET_ALIGNMENT = 16
  • struct tpacket_hdr
  • pad to TPACKET_ALIGNMENT = 16
  • struct sockaddr_ll
  • Разрыв, выбранный так, чтобы пакетные данные (Start + tp_net) совпали с TPACKET_ALIGNMENT = 16
  • Start + tp_mac: [необязательный заголовок MAC]
  • Start + tp_net: пакетные данные, выровненные по TPACKET_ALIGNMENT = 16.
  • Пэд для выравнивания по TPACKET_ALIGNMENT = 16

    * /

Если данные начинаются с Start + tp_net, то почему код в примере вычитает sizeof (struct 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);

Это похоже на повреждение данных, адрес сокета и необязательный mac-адрес будут перезаписаны данными для передачи. В моем случае, если я использую этот код, заголовок пакета UDP будет перезаписан, это правильно?

Заранее спасибо

1 Ответ

3 голосов
/ 12 ноября 2011

Извините, я немного опоздал. У меня была та же проблема, и, к сожалению, использование 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   ./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]

MAC-адрес получателя - 00: 01: 02: 03: 04: 05, а MAC-адрес источника 06: 07: 08: 09: 0a: 0b. И данные начинаются (сразу после заголовка Ethernet) с 0x0e (14).

Таким образом, смещение данных примера программы является началом пакета (ethernet) для отправки.

Так что это действительно правильный способ заполнения буфера для отправки (убедитесь, что pktlen не больше размера вашего кадра):

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

И никакие данные не будут перезаписаны. Но вы должны предоставить Ethernet, IP и UDP заголовок самостоятельно.

EDIT: Для TX_Ring структура кадра выглядит следующим образом:

  • Start. Кадр должен быть выровнен по TPACKET_ALIGNMENT = 16
  • struct tpacket_hdr (размер = 32 байта)
  • pad to TPACKET_ALIGNMENT = 16 (поэтому эффективный размер заполнения равен 0)
  • пакет данных
  • Пэд для выравнивания по TPACKET_ALIGNMENT = 16 (поэтому следующий кадр выровнен по 16-битам)
...