Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 17.8. Receive Interrupt Mitigation

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

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

17.8 Подавление приема прерываний

hardorsoft 26.10.10 в 02:57

0

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

hardorsoft 26.10.10 в 02:57

0

Для улучшения производительности Linux-систем, разработчики
сетевой подсистемы могут создать альтернативный интерфейс
(называемый NAPI)1, в основе которого лежит механизм опроса. Слово
«опрос» может не понравиться тем разработчикам драйверов, которые
видели много неэффективных и не элегантных технологий опроса. Но,
опрос не эффективен, только тогда, когда интерфейс не получает работы,
ведя опрос. Когда в системе имеется высокопроизводительный
интерфейс, обрабатывающий большой трафик, то всегда есть пакеты для
обработки. В такой ситуации можно обойтись без прерываний. Нужно
только, чтобы новые пакеты забирались из интерфейса достаточно часто.

hardorsoft 26.10.10 в 02:58

0

[NAPI] означает "новый API", у иследователей лучше получатеся создавать интерфейсы чем называть их.

hardorsoft 26.10.10 в 03:04

0

Прекращение приема прерываний может существенно разгрузить
процессор. Также , NAPI драйвер может не передавать пакеты в ядро,
если этих пакетов мало, а накапливать их в сетевом коде, для еще
большего повышения производительности. По различным причинам, в
NAPI драйверах уменьшается вероятность изменения порядка следования
пакетов.

hardorsoft 26.10.10 в 02:58

0

Не все устройства могут работать в NAPI режиме. NAPI –
совместимый интерфейс должен иметь возможность сохранения
нескольких пакетов, внутри карты или во встроенной памяти для ПДП.
Интерфейс должен обеспечивать возможность запрещения прерываний
при получении пакета, в тоже время продолжать выдавать прерывания
при завершении отправки пакета и других событиях. Есть и другие
тонкости, при написании NAPI-совместимого драйвера. О них можно
прочитать в файле Documentation/networking/NAPI_HOWTO.txt, в исходных
кодах ядра.

hardorsoft 26.10.10 в 02:58

0

Относительно мало драйверов реализуют интерфейс NAPI. Имеет
смысл потратить время на реализацию NAPI, если вы пишите драйвер
интерфейса, который генерирует огромное количество прерываний.

hardorsoft 26.10.10 в 02:58

0

Когда драйвер snull загружается с параметром use_napi не равным
нулю, он работает в режиме NAPI. При инициализации мы настраиваем 2
поля внешней структуры net_device.

hardorsoft 26.10.10 в 02:59

0

if (use_napi) {
dev->poll = snull_poll;
dev->weight = 2;
}

hardorsoft 26.10.10 в 03:05

0

Поле poll должно указывать на функцию опроса, в нашем случае -
snull_poll. Поле weight описывает, на сколько большой трафик может
быть обработан устройством. Не существует строгих правил для выбора
значения этого параметра. По соглашению, Ethernet-интерфейс
производительностью 10MBps использует weight = 16, а более быстрый
weight = 64. Не заносите в weight значение, превышающее количество
пакетов, которое может хранить ваш интерфейс. В snull мы
устанавливаем weight= 2, для демонстрации отсроченного приема
пакетов.

hardorsoft 26.10.10 в 03:05

0

Следующим шагом в создании NAPI-совместимого драйвера, внесем
изменения в обработку прерывания. Когда ваш интерфейс (в начале
прием прерываний - разрешен) сигнализирует о прибытии пакета,
обработчик прерывания не обрабатывает этот пакет. Вместо этого, запрещается дальнейший прием прерываний, а ядру сообщается, что пора
начинать опрос устройства. В snull, обработка прерывания по событию
приема пакета, изменяется:

hardorsoft 26.10.10 в 03:06

0

if (statusword & SNULL_RX_INTR) {
snull_rx_ints(dev, 0); /* Запрещаем прерывания */
netif_rx_schedule(dev);
}

hardorsoft 26.10.10 в 03:07

0

Когда интерфейс информирует о том, что прибыл пакет, обработка
прерываний – прекращается. Далее необходимо вызвать
netif_rx_schedule, благодаря чему в будущем произойдет вызов метода
poll.

hardorsoft 26.10.10 в 03:07

0

Когда интерфейс информирует о том, что прибыл пакет, обработка
прерываний – прекращается. Далее необходимо вызвать
netif_rx_schedule, благодаря чему в будущем произойдет вызов метода
poll.

hardorsoft 26.10.10 в 03:08

0

int (*poll)(struct net_device *dev, int *budget);

hardorsoft 26.10.10 в 03:08

0

Реализация в snull метода poll:

hardorsoft 26.10.10 в 03:08

0

static int snull_poll(struct net_device *dev, int *budget)
{
int npackets = 0, quota = min(dev->quota, *budget);
struct sk_buff *skb;
struct snull_priv *priv = netdev_priv(dev);
struct snull_packet *pkt;
while (npackets < quota && priv->rx_queue) {
pkt = snull_dequeue_buf(dev);
skb = dev_alloc_skb(pkt->datalen + 2);
if (! skb) {
if (printk_ratelimit())
printk(KERN_NOTICE "snull: packet dropped\n");
priv->stats.rx_dropped++;
snull_release_buffer(pkt);
continue;
}
memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY; /* не проверяем */
netif_receive_skb(skb);
/* статистика */
npackets++;
priv->stats.rx_packets++;
priv->stats.rx_bytes += pkt->datalen;
snull_release_buffer(pkt);
}
/* если обработали все пакеты, сообщаем об этом ядру и разрешаем
прерывания */
*budget -= npackets;
dev->quota -= npackets;
if (! priv->rx_queue) {
netif_rx_complete(dev);
snull_rx_ints(dev, 1);
return 0;
}
/* Мы не смогли все обработать */
return 1;
}

hardorsoft 26.10.10 в 03:08

0

В центральной части функции создается skb, хранящий пакет. Этот
код аналогичен рассмотренному ранее snull_rx, но есть отличия:

hardorsoft 26.10.10 в 03:09

0

Параметр budget содержит максимальное количество пакетов,
которое может быть передано ядру. В структуре dev поле quota
предоставляет другое максимальное значение. Метод poll
должен использовать наименьшее из них. Это приводит к
снижению количества реально принимаемых пакетов. budget –
максимальное количество пакетов, которое может принять
текущий процессор. quota – ограничение интерфейса, обычно
оно устанавливается при инициализации, как и weight.

hardorsoft 26.10.10 в 03:09

0

Пакет передается ядром с помощью функции
netif_receive_skb, что лучше чем netif_rx.

hardorsoft 26.10.10 в 03:09

0

Если метод poll обработал все пакеты, то снова разрешается
прием прерываний, прекращается опрос (netif_rx_complete),
и возвращается 0. Если обработаны не все пакеты –
возвращается 1.

hardorsoft 26.10.10 в 03:09

0

Сетевая подсистема гарантирует, что метод устройства poll не
будет выполняться одновременно на нескольких процессорах. Конечно,
методы poll для различных устройств, могут выполняться одновременно.

hardorsoft 26.10.10 в 03:10

0
Минутку...