Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 17.10. The Socket Buffers

Оглавление
Английский оригинал Перевод на русский

Сожалеем, но текст оригинала доступен только зарегистрированным пользователям.

17.10. Буферы сокетов

hardorsoft 26.10.10 в 03:13

0

Мы рассмотрели большинство вопросов, связанных с сетевыми
интерфейсами. Но все еще не рассмотрели детально структуру sk_buff.
Структура является сердцевиной сетевой подсистемы Linux, мы
рассмотрим два главных поля структуры, и функции для работы с ними.

hardorsoft 26.10.10 в 03:13

0

Хотя, точное понимание содержимого sk_buff не обязательно, но
это может помочь вам при поиске проблем и при оптимизации кода.
Например, если вы взгляните на loopback.c, вы увидите оптимизацию,
основанную на понимании содержимого sk_buff. Здесь надо
предупредить: если вы пишите код использующий содержимое sk_buff, то
вы должны быть готовы кое-что переделать, в будущих реализациях ядра.
До сих пор, издержки разработки оправдывались уменьшением издержек
в эксплуатации.

hardorsoft 26.10.10 в 03:13

0

Мы не описываем здесь всю структуру и поля, которые могут быть
использованы в драйвере. Если вы хотите узнать больше, ознакомитесь с
файлом <linux></linux>skbuff.h>, там определены структуры и объявлены
прототипы функций. Дополнительную информацию о том, какие функции
и поля могут быть использованы, можно без труда найти в исходных
текстах ядра.

hardorsoft 26.10.10 в 03:13

0

17.10.1. Важные поля

hardorsoft 26.10.10 в 03:13

0

17.10.1. Важные поля

hardorsoft 26.10.10 в 03:13

0

Перечисленные здесь поля могут быть необходимы драйверу. Они
приведены не упорядочено.

hardorsoft 26.10.10 в 03:14

0

struct net_device *dev;

hardorsoft 26.10.10 в 03:14

0

устройство посылает и принимает этот буфер.

hardorsoft 26.10.10 в 04:11

0

union { /* ... */ } h;
union { /* ... */ } nh;
union { /*... */} mac;

hardorsoft 26.10.10 в 03:14

0

Указатели на заголовки различного уровня, содержащиеся в
пакете. Каждое поле union – указатель на различные типы
структур данных. h – указатели на заголовки транспортного
уровня (например, структура tcphdr *th); nh – заголовки
сетевого уровня (такие как iphdr *iph); mac - коллекция
указателей на заголовки канального уровня (link-layer) (такие как
ethdr *ethernet).

hardorsoft 26.10.10 в 04:12

0

Если вашему драйверу требуется адрес отправителя и получателя
TCP пакета, он может найти его в skb-&gt;h.th. Для получения
полного набора заголовков типов, к которым можно получить
доступ таким образом, смотрите заголовочный файл.

hardorsoft 26.10.10 в 04:12

0

Обратите внимание на то, что драйверы сетевых устройств
отвечают за установку указателя mac в поступающих пакетах. Эта
задача обычно выполняется eth_type_trans, но не Еthernet-
драйверы должны сами установить skb->mac.raw, как показано в
подразделе "Не Ethernet-заголовки "

hardorsoft 26.10.10 в 04:13

0

unsigned char *head;
unsigned char *data;
unsigned char *tail;
unsigned char *end;

hardorsoft 26.10.10 в 03:14

0

Указатели используются для адресации данных в пакете. head
укатывает на начало выделенного пространства, data – начало
доступных октетов (обычно data больше чем head), tail – конец
доступных октетов, end – содержит максимальный адрес, который
может достичь tail. Иными словами, с skb->end по skb->head
находится доступное пространство буфера, в котором
используется пространство размером (skb->tail – skb->data).

hardorsoft 26.10.10 в 04:14

0

unsigned int len;
unsigned int data_len;

hardorsoft 26.10.10 в 03:14

0

len – полное количество данных в пакете, data_len – длинна
фрагментированной части пакета. data_len содержит «0», если
сегментированный ввод-вывод (scatter/gather I/O) не
используется.

hardorsoft 26.10.10 в 04:14

0

unsigned char ip_summed;

hardorsoft 26.10.10 в 03:14

0

Контрольная сумма для этого пакета. Поле устанавливается
драйвером при прибытии пакета, как описано в подразделе
«Прием пакетов»

hardorsoft 26.10.10 в 04:14

0

unsigned char pkt_type;

hardorsoft 26.10.10 в 03:15

0

Используется для классификации пакетов. Драйвер
устанавливает это поля в PACKET_HOST (этот пакет для меня),
PACKET_OTHERHOST (этот пакет для не меня),
PACKET_BROADCAST или PACKET_MULTICAST. Ethernet-драйвер
не модифицирует это поле явно, т.к. за него это делает
eth_type_trans.

hardorsoft 26.10.10 в 04:15

0

shinfo(struct sk_buff *skb);
unsigned int shinfo(skb)->nr_frags;
skb_frag_t shinfo(skb)->frags;

hardorsoft 26.10.10 в 03:15

0

Для повышения производительности, некоторая информация skb,
храниться в отдельной структуре, которая находится сразу после
skb в памяти. Эта «совместно используемая информация» (так
названа потому, что может быть совместно использоваться
копиями skb в сетевом коде) может быть доступна через макрос
shinfo. Большинство полей этой структуры выходит за рамки
данной книги. Мы рассмотрим nr_frags и frags в подразделе
«Сегментированный ввод-вывод».

hardorsoft 26.10.10 в 04:15

0

Оставшиеся поля в структуре не очень интересны. Они
используются для хранения списка буферов, учета памяти буферов
сокетов, и т.д.

hardorsoft 26.10.10 в 04:15

0

17.10.2. Функции работы с буферами сокетов.

hardorsoft 26.10.10 в 04:15

0

Сетевые устройства выполняют различные действия над структурой
sk_buff, через служебные функции интерфейса. Многие функции
работают с буферами сокетов. Вот наиболее интересные:

hardorsoft 26.10.10 в 04:16

0

struct sk_buff *alloc_skb(unsigned int len, int priority);
struct sk_buff *dev_alloc_skb(unsigned int len);

hardorsoft 26.10.10 в 03:15

0

Выделение буфера. Функция alloc_skb выделяет буфер и
инициализирует skb->data, и skb->tail к skb->head. Функция
dev_alloc_skb является сокращенным вызовом alloc_skb с
приоритетом GFP_ATOMIC и резервированием некоторого
пространства между skb->head и skb->data. Это пространство
используется в оптимизации сетевого уровня, и не затрагивает
драйвер.

hardorsoft 26.10.10 в 04:16

0

void kfree_skb(struct sk_buff *skb);
void dev_kfree_skb(struct sk_buff *skb);
void dev_kfree_skb_irq(struct sk_buff *skb);
void dev_kfree_skb_any(struct sk_buff *skb);

hardorsoft 26.10.10 в 03:15

0

Функции освобождают буфер. Вызов kfree_skb используется
ядром. Драйвер использует одну из форм kfree_skb:
dev_kfree_skb – вызывается не в контексте прерывания;
dev_kfree_skb_irq – вызывается в контексте прерывания;
dev_kfree_skb_any – для кода, который может работать в
любом контексте.

hardorsoft 26.10.10 в 04:17

0

unsigned char *skb_put(struct sk_buff *skb, int len);
unsigned char *_ _skb_put(struct sk_buff *skb, int len);

hardorsoft 26.10.10 в 03:15

0

Обновляют поля tail и len в структуре sk_buff. Функции
используются для добавления данных к концу буфера. Каждая
функция возвращает предыдущее значение skb->tail (другими
словами указатель на только что созданное пространство).
Драйвер может использовать возвращаемое значение для
копирования: memcpy(skb_put(...), data, len) или подобным
образом. Функции отличаются тем, что skb_put проверяет,
помещаются ли данные в буфере, тогда как __skb_put – не
проверяет.

hardorsoft 26.10.10 в 04:17

0

unsigned char *skb_push(struct sk_buff *skb, int len);
unsigned char *_ _skb_push(struct sk_buff *skb, int len);

hardorsoft 26.10.10 в 03:15

0

Функция уменьшает skb->data и увеличивает skb->len. Работает
аналогично skb_put, но данные добавляются в начало пакета, а не
в конец. Возвращается указатель на созданное пространство.
Функция используется для добавления аппаратного заголовка
перед отправкой пакета. Отличие __skb_push в том, что проверка
на наличие свободного пространства не производиться.

hardorsoft 26.10.10 в 04:18

0

int skb_tailroom(struct sk_buff *skb);

hardorsoft 26.10.10 в 03:15

0

возвращает размер доступного пространства в буфере для
приходящих данных. Если драйвер помещает больше данных, чем
может вместить буфер, происходит критическая ошибка
системы(system panics). Хотя Вы могли бы возразить, что вызова
printk будет достаточно, для того чтобы отметить ошибку, но
искажение содержимого памяти может быть настолько вредно для
системы, что разработчики решили предпринять категоричное
действие. Практически, вы не должны проверять доступное
пространство, если буфер был распределен правильно. Драйверы
обычно получают размер пакета перед выделением буфера,
только не корректно реализованные драйвера помещают слишком
много данных в буфер, вследствии чего получают критическую
ошибку.

hardorsoft 26.10.10 в 04:18

0

int skb_headroom(struct sk_buff *skb);

hardorsoft 26.10.10 в 03:16

0

Возвращает количество доступного пространства перед началом
данных, сообщая, сколько октет можно поместить посредством
skb_push в буфер.

hardorsoft 26.10.10 в 04:19

0

void skb_reserve(struct sk_buff *skb, int len);
Увеличивает data и tail. Функция может быть использована для
резервирования пространства перед заполнением буфера.
Большинство Ethernet-интерфейсов резервируют 2 байта в начале
пакета, после 14-байтного заголовка Ehernet; поэтому ip-
заголовок выровнен по 16-байтной границе. snull делает также,
хотя эти команды не показаны в подразделе «Прием пакетов»,
чтобы не вводить дополнительные понятия.

hardorsoft 26.10.10 в 04:19

0

unsigned char *skb_pull(struct sk_buff *skb, int len);

hardorsoft 26.10.10 в 03:16

0

Удаляет данные из начала пакета. Драйверу нет необходимости
использовать эту функцию, но она приведена здесь для полноты
описания. Функция уменьшает skb->len и увеличивает skb->data.
Эти действия удаляют аппаратный заголовок (Ethernet или
подобный) находящийся в начале пришедшего пакета.

hardorsoft 26.10.10 в 04:19

0

int skb_is_nonlinear(struct sk_buff *skb);

hardorsoft 26.10.10 в 03:16

0

Возвращает true если этот skb разделен на несколько фрагментов
для сегментированного ввода-вывода (scatter/gather I/O).

hardorsoft 26.10.10 в 04:19

0

int skb_headlen(struct sk_buff *skb);

hardorsoft 26.10.10 в 03:16

0

Возвращает длину первого сегмента skb (часть на которую
указывает skb->data).

hardorsoft 26.10.10 в 04:22

0

void *kmap_skb_frag(skb_frag_t *frag);
void kunmap_skb_frag(void *vaddr);

hardorsoft 26.10.10 в 03:16

0

Если вам необходим прямой доступ к фрагментам в нелинейном
skb из ядра, то вам будут нужны эти функции. kmap используется
атомарно, и вы не сможете отобразить более одного фрагмента
одновременно.

hardorsoft 26.10.10 в 04:22

0

В ядре определены и другие функции, работающие с буферами
сокетов, но они предназначены для работы на более высоком уровне
сетевого кода, и драйверу они не нужны.

hardorsoft 26.10.10 в 04:22

0
Минутку...