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

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

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

17.4. Групповая адресация

hardorsoft 26.10.10 в 05:28

0

17.4. Групповая адресация

hardorsoft 26.10.10 в 05:28

0

Пакеты с групповой адресацией (multicast-пакеты) – предназначены
для приема более чем одним хостом, но не всеми хостами. Эта
возможность реализуется назначением специальных аппаратных адресов
для группы хостов. Пакеты направляются на один специальный адрес, и
принимаются всеми хостами в группе. В случае Ethernet, групповой адрес
отличается тем, что в нем установлен младший бит, в первом октете
адреса. А каждое устройство очищает этот бит в аппаратном адресе.

hardorsoft 26.10.10 в 05:28

0

Наиболее сложная часть работы с группами хостов и аппаратными
адресами выполняется не драйвером, а приложениями и ядром.

hardorsoft 26.10.10 в 05:28

0

Наиболее сложная часть работы с группами хостов и аппаратными
адресами выполняется не драйвером, а приложениями и ядром.

hardorsoft 26.10.10 в 05:28

0

Передавать multicast-пакеты – просто, это делается также как и для
остальных пакетов. Интерфейс передает пакеты через
коммуникационную среду, без анализа адреса назначения. Ядро
назначает корректный аппаратный адрес, и метод устройства
hard_header, если он определен, не должен анализировать этот адрес.

hardorsoft 26.10.10 в 05:28

0

Ядро отслеживает, какие multicast-адреса интересны хосту в
настоящее время. Список может часто меняться, поскольку этим могут
заниматься работающие приложения и пользователи. Драйвер должен
принимать список multicast-адресов, и передавать ядру пакеты,
посланные этим адресам. От того, как работает аппаратное обеспечение,
зависит как в драйвере реализовано хранение списка multicast-адресов.
Обычно, по тому, как аппаратура работает с групповой адресацией, она
делится на 3 категории:

hardorsoft 26.10.10 в 05:29

0

Интерфейсы, которые не могут работать с групповой
адресацией. Эти интерфейсы или принимают пакеты,
предназначенные только для их аппаратных адресов (плюс
широко вещательные пакеты), или принимают все пакеты. Они
могут принимать multicast-пакеты, только обрабатывая каждый
пакет, поэтому операционной системе придется иметь дело с
огромным количеством ненужных пакетов. Обычно эти
интерфейсы не поддерживают групповую адресацию, и не
устанавливают флаг IFF_MULTICAST в dev->flags.

hardorsoft 26.10.10 в 05:29

0

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

hardorsoft 26.10.10 в 05:29

0

Интерфейс может отличать пакты с групповой адресацией от
прочих (пакетов идущих от хоста к хосту или
широковещательных). Эти интерфейсы могут быть настроены
на прием каждого multicast-пакета. В этом случае необходимо
программно определять по адресу пакета, интересует ли он
данный хост. Нагрузка в этом случае приемлема, поскольку в
обычной сети количество multicast-пакетов – не велико.

hardorsoft 26.10.10 в 05:30

0

Интерфейсы, которые могут выполнять аппаратное

детектирование multicast-адресов. Эти интерфейсы могут,
просматривая список multicast-адресов, принимать или
игнорировать пакеты с групповой адресацией. Для ядра эти
интерфейсы – оптимальны, поскольку не нужно тратить
процессорное время на обработку не нужных пакетов.

hardorsoft 26.10.10 в 05:30

0

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

hardorsoft 26.10.10 в 05:30

0

17.14.1. Поддержка ядром групповой адресации

hardorsoft 26.10.10 в 05:31

0

Для групповой адресации используются:
структура данных и флаги устройства.

hardorsoft 26.10.10 в 05:31

0

void (*dev->set_multicast_list)(struct net_device *dev);

hardorsoft 26.10.10 в 05:31

0

Этот метод вызывается при изменении списка multicast-адресов,
ассоциированных с устройством. Также вызывается при
модификации dev->flags, т.к. некоторые флаги (например
IFF_PROMISC) нуждаются в репрограммировании аппаратного
фильтра. Метод принимает указатель struct net_device *dev, в
качестве аргумента, и возвращает void. Драйвер, не реализующий
этот метод, может установить это поле в NULL.

hardorsoft 26.10.10 в 05:32

0

struct dev_mc_list *dev->mc_list;

hardorsoft 26.10.10 в 05:31

0

Список всех групповых адресов, ассоциированных с устройством.
Определение структуры приведено в конце подраздела.

hardorsoft 26.10.10 в 05:32

0

int dev->mc_count;

hardorsoft 26.10.10 в 05:31

0

Размер списка. Эта информация несколько избыточна, но проверка
dev->mc_count==0, выполняется быстрее.

hardorsoft 26.10.10 в 05:32

0

IFF_MULTICAST

hardorsoft 26.10.10 в 05:31

0

Драйверам не устанавливающих этот флаг в dev->flags, интерфейс
предлагает обработку пакетов с групповой адресацией. Однако ядро
вызывает метод set_multicast_list когда изменяется dev->flags,
т.к. Список mc_list может меняться при не активном интерфейсе.

hardorsoft 26.10.10 в 05:33

0

IFF_ALLMULTI

hardorsoft 26.10.10 в 05:32

0

Флаг устанавливается в dev->flags, когда требуется, чтобы драйвер
принимал все пакты с групповой адресацией из сети. Это
происходит, когда разрешена multicast-маршрутиризация. При
установленном флаге фильтрация пакетов по dev->mc_list не
производится.

hardorsoft 26.10.10 в 05:33

0

IFF_PROMISC

hardorsoft 26.10.10 в 05:32

0

Установка этого флага переводит интерфейс в не разборчивый
(promiscuous) режим. Когда установлен этот флаг, каждый пакет
принимается из сети не зависимо от dev->mc_list.

hardorsoft 26.10.10 в 05:33

0

Последний бит информации, необходимой разработчику драйвера,
это определение структуры dev_mc_list, которое находится в
<"linux/netdevice.h">:

hardorsoft 26.10.10 в 05:33

0

struct dev_mc_list {
struct dev_mc_list
__u8
unsigned char
int
int
};

hardorsoft 26.10.10 в 05:34

0

Т.к. групповая адресация и аппаратные адреса независимы от среды
передачи пакетов, эта структура портируется на различные сетевые
реализации, и каждый адрес рассматривается как строка октетов
некоторой длинны, так же как и dev->dev_addr.

hardorsoft 26.10.10 в 05:34

0

17.14.2. Типичная реализация

hardorsoft 26.10.10 в 05:34

0

Наилучшим образом описать работу set_multicast_list можно,
показав вам псевдокод.

hardorsoft 26.10.10 в 05:34

0

Приведенная ниже функция – типичная реализация
полнофункционального драйвера. Драйвер в этом интерфейсе управляет
аппаратным фильтром пакетов, который содержит таблицу multicast-
адресов, принимаемых хостом. Максимальный размер таблицы –
FF_TABLE_SIZE.

hardorsoft 26.10.10 в 05:34

0

Функции с префиксом 'ff_', выполняют аппаратно-зависимые
операции.

hardorsoft 26.10.10 в 05:35

0

void ff_set_multicast_list(struct net_device *dev)
{
struct dev_mc_list *mcptr;
if (dev->flags & IFF_PROMISC) {
ff_get_all_packets( );
return;
}
/* если присутствует больше адресов, чем мы можем обработать,
то получаем все multicast-пакеты и обрабатываем их программно*/
if (dev->flags & IFF_ALLMULTI || dev->mc_count > FF_TABLE_SIZE) {
ff_get_all_multicast_packets( );
return;
}
/* нет multicast-пакетов? Тогда получаем предназначенные нам*/
if (dev->mc_count = = 0) {
ff_get_only_own_packets( );
return;
}
/* передадим все адреса в аппаратный фильтр */
ff_clear_mc_list( );
for (mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next)
ff_store_mc_address(mc_ptr->dmi_addr);
ff_get_packets_in_multicast_list( );
}

hardorsoft 26.10.10 в 05:35

0

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

hardorsoft 26.10.10 в 05:35

0

Ранее упоминалось, что интерфейс, который не может работать с
multicast-пакетами, все же нуждается в методе set_multicast_list, для
уведомлении об изменении dev->flags. Этот подход может быть назван
“nonfeatured” (nf) – не характерной реализацией. Реализация очень
проста, и показана ниже:

hardorsoft 26.10.10 в 05:35

0

void nf_set_multicast_list(struct net_device *dev)
{
if (dev->flags & IFF_PROMISC)
nf_get_all_packets( );
else
nf_get_only_own_packets( );
}

hardorsoft 26.10.10 в 05:35

0

Использование флага IFF_PROMISC – необходимо, т.к. иначе
пользователь не мог бы использовать tcpdump или другой анализатор
трафика сети. Если интерфейс работает на соединении точка-точка, то
нет необходимости реализовывать set_multicast_list, т.к. все равно
принимается каждый пакет.

hardorsoft 26.10.10 в 05:36

0
Минутку...