Статическое smp_affinity на хосте Linux

Вопрос или проблема

У меня есть сетевая карточка Intel i210, которая поддерживает 4 объединенных fifo канала. Я хочу распределить обработчики прерываний от этих каналов среди первых 4 ядер в моей системе.

Я пробовал добавить правило udev, которое будет срабатывать на событие ADD от ядра:

/etc/udev/rules.d/98-i210-network-card.rules:

ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/...", RUN+="/usr/local/bin/spread-i210-irq-handlers.sh"

/usr/local/bin/spread-i210-irq-handlers.sh:

set -exuo pipefail
# распределить IRQ по CPU 0-3
proc_curr=0
proc_max=4
for irq_path in /sys/$DEVPATH/msi_irqs/*; do
  irq=$(basename $irq_path)
  echo $proc_curr > /proc/irq/$irq/smp_affinity_list
  proc_curr=$(( (proc_curr + 1) % proc_max ))
done

Но проблема в том, что файл /proc/irq/$irq/smp_affinity_list в этот момент не существует.

Как правильно статически настроить smp_affinity_list для какого-либо устройства?

Ответ или решение

Для статической настройки параметра smp_affinity для обработчиков прерываний (IRQ) сетевой карты Intel i210 на Linux, вы можете использовать несколько методов, чтобы убедиться, что настройки применяются корректно после добавления устройства.

1. Использование udev правил

Ваше текущее правило udev имеет правильную направленность, однако оно не учитывает, что пункт назначения для установки значений smp_affinity может быть недоступен в момент выполнения скрипта. Это может происходить из-за того, что файл /proc/irq/$irq/smp_affinity_list не создан в момент активации правила.

Корректировка вашего решения:

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

#!/bin/bash
set -exuo pipefail

# spread IRQs across CPUs 0-3
proc_curr=0
proc_max=4

for irq_path in /sys/$DEVPATH/msi_irqs/*; do
  irq=$(basename $irq_path)

  # Проверяем, что сможем записать, обязательно используем цикл для ожидания
  while [ ! -e /proc/irq/$irq/smp_affinity_list ]; do
    sleep 1
  done

  echo $proc_curr > /proc/irq/$irq/smp_affinity_list
  proc_curr=$(( (proc_curr + 1) % proc_max ))
done

2. Альтернативный подход с использованием systemd службы

Если вы хотите более устойчивое решение, можно создать системную службу, которая будет необходима для периодического выполнения скрипта настройки smp_affinity.

  1. Создайте новый сервис-файл:
sudo nano /etc/systemd/system/spread-i210-irq-handlers.service

Добавьте в него следующее содержимое:

[Unit]
Description=Spread IRQ handlers across CPU cores
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/spread-i210-irq-handlers.sh

[Install]
WantedBy=multi-user.target
  1. Включите службу, чтобы она запускалась при каждой загрузке:
sudo systemctl enable spread-i210-irq-handlers.service
  1. Запустите службу:
sudo systemctl start spread-i210-irq-handlers.service

3. Мониторинг и отладка

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

cat /proc/interrupts

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

Оцените материал
Добавить комментарий

Капча загружается...