Могу ли я иметь более 32 сокетов netlink в пространстве ядра?

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

Моя проблема в том, что эти розетки мешают друг другу. Это связано с тем, что все они регистрируются в одном и том же семействе адресов Netlink (потому что их не так много для начала - макс. 32 и более половины уже зарезервировано), а также потому, что все они привязываются к одному и тому же pid (pid ядра - ноль).

Хотелось бы, чтобы было больше места для адресных семей. Или, еще лучше, я хотел бы привязать свои сокеты к другим pid. Почему Netlink является предпочтительным каналом пользовательского ядра, если одновременно могут быть открыты только 32 сокета?

В документации по libnl-3 говорится

Адрес (порт) netlink состоит из 32-битного целого числа. Порт 0 (ноль) зарезервирован для ядра и относится к сокету на стороне ядра каждого семейства протоколов netlink. Другие номера портов обычно относятся к сокетам, принадлежащим пользовательскому пространству, хотя это не является обязательным.

Это последнее утверждение сейчас кажется ложью. Ядро использует в качестве pid константу и не экспортировать более универсальные функции:

if (netlink_insert(sk, 0))
    goto out_sock_release;

Думаю, я могу перекомпилировать ядро ​​и увеличить лимит семейства адресов. Но это модули ядра; Мне не следовало этого делать.

Я что-то упускаю?


person Yd Ahhrk    schedule 01.10.2015    source источник
comment
Согласно источникам ядра, все сокеты netlink на стороне ядра хранятся в едином заранее выделенном массиве (nl_table) и индексируются по номеру протокола. Таким образом, у вас не может быть больше 32 (размер массива) сокетов netlink. Но ничто не мешает вам использовать один сокет и отправлять ему сообщения в соответствии с каким-то предопределенным полем в этих сообщениях. Таким образом, у вас будет несколько виртуальных сокетов.   -  person Tsyvarev    schedule 02.10.2015
comment
Другими словами, @Tsyvarev ... я должен закодировать специальный новый модуль, который будет создавать сокет ... а затем мультиплексировать сообщения этого сокета через другие модули. Ты прав; это один из способов решить эту проблему, хотя это гораздо больше проблем, чем следовало бы. Возможно, это в конечном итоге будет принятым ответом, хотя я бы предпочел немного подождать, чтобы увидеть больше мнений.   -  person Yd Ahhrk    schedule 02.10.2015


Ответы (2)


No.

Ограничение количества сокетов Netlink является причиной существования Generic Netlink.

Generic Netlink - это слой поверх стандартного Netlink. Вместо того, чтобы открывать сокет, вы регистрируете обратный вызов на уже установленном сокете и слушаете сообщения, направленные в «подсемейство». Учитывая, что имеется больше доступных семейств слотов (1023) и нет портов, я предполагаю, что они сочли разделение между семействами и портами ненужным на этом уровне.

Чтобы зарегистрировать слушателя в пространстве ядра, используйте _1 _ или его братьев и сестер. В пространстве пользователя Generic Netlink можно использовать через API libnl-3 (хоть и ограниченно, но код много говорит и открыт).

person Yd Ahhrk    schedule 10.11.2015

Вас смущает MAX_LINKS имя переменной. Это не «максимальное количество ссылок», это «максимальное количество семейств». Вы перечислили семейства сетевых ссылок или группы сетевых ссылок IOW. Действительно, существует 32 семьи. Каждая семья посвящена определенной цели. Например, NETLINK_SELINUX - для уведомлений SELinux, а NETLINK_KOBJECT_UEVENT - для уведомлений kobject (это то, что обрабатывает udev).

Но ограничений по количеству розеток для каждой семьи нет.

Когда вы вызываете netlink_create, он проверяет номер вашего протокола, который в случае сокета netlink является семейством netlink, например NETLINK_SELINUX. Посмотрите код

static int netlink_create(struct net *net, struct socket *sock, int protocol,
                           int kern)
{
...
         if (protocol < 0 || protocol >= MAX_LINKS)
                 return -EPROTONOSUPPORT;
...

Вот как используется ваш MAX_LINKS.

Позже, когда фактически создается сокет, он вызывает __netlink_create < / a>, который, в свою очередь, вызывает _8 _, который, в свою очередь, вызывает _9 _. Теперь в sk_prot_alloc он выделяет сокет с помощью kmallocing (netlink не имеет собственного блочного кеша):

slab = prot->slab;
if (slab != NULL) {
    sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
    if (!sk)
        return sk;
    if (priority & __GFP_ZERO) {
        if (prot->clear_sk)
            prot->clear_sk(sk, prot->obj_size);
        else
            sk_prot_clear_nulls(sk, prot->obj_size);
    }
} else
    sk = kmalloc(prot->obj_size, priority);
person Alexander Dzyoba    schedule 02.10.2015
comment
Хм ... извините; Не думаю, что вы видите мою проблему. Да, я знаю, что 32 относится к семьям. В идеале я бы хотел открыть больше розеток на семью. Мне мешает тот факт, что каждое семейство может иметь один pid (порт) представителя в пространстве ядра. Я думал использовать семейства как хакер, чтобы открыть больше сокетов, но потом я привязал себя к максимуму 32. Но это всего лишь взлом. - person Yd Ahhrk; 02.10.2015
comment
Важно то, что если я запускаю netlink_kernel_create(net, NETLINK_USERSOCK, &cfg) после того, как он привязывается к нулевому pid семейства usersock. Если я сделаю это второй раз, это не удастся, предположительно потому что pid ноль из семейства usersock уже занят. Кажется, нет никакого способа указать функции, какой pid я хочу использовать. - person Yd Ahhrk; 02.10.2015