Можно ли использовать package_mmap в Linux без root-доступа?

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

Часто packet_mmap используется для непосредственного просмотра всех пакетов в сети, для чего требуется root-доступ. Мое приложение требует только использования стандартного интерфейса UDP-сокета Linux. Я хочу использовать package_mmap исключительно для повышения эффективности — прямо сейчас системные вызовы потребляют более 50% циклов моего процессора.

Есть ли способ настроить packet_mmap таким образом, чтобы его можно было использовать из пользовательского пространства?


person charliehorse55    schedule 01.03.2013    source источник
comment
В Unix стандартным методом повышения привилегий является бит setuid. ИМХО было бы неправильно использовать такую ​​функцию без повышения прав.   -  person Paulo Scardine    schedule 01.03.2013
comment
Мне интересно, есть ли способ ограничить то, что я могу с ним делать, чтобы мне было разрешено использовать его из пользовательского пространства.   -  person charliehorse55    schedule 01.03.2013


Ответы (2)


Глядя на Git-репозиторий ядра Linux, кажется, что ни PF_INET, ни PF_INET6 сокеты не поддерживают доступ с отображением памяти, поэтому, если

Мое приложение требует только использования стандартного интерфейса UDP-сокета Linux. Я хочу использовать package_mmap исключительно для повышения эффективности — прямо сейчас системные вызовы потребляют более 50% циклов моего процессора.

вы имеете в виду, что хотите использовать доступ с отображением памяти для обычного сокета UDP или TCP, к сожалению, вы не можете. То же самое относится и к необработанным IP-сокетам.

PF_PACKET сокеты поддерживают доступ с отображением памяти, но для них требуются повышенные привилегии, независимо от того, используете ли вы доступ с отображением памяти или нет. Они не заменяют сокеты PF_INET или PF_INET6; они представляют собой механизм для чтения и записи пакетов канального уровня, поэтому, если вы хотите запускать на них обычные интернет-приложения, удачи:

  1. вам придется переопределить IP и любой транспортный протокол, который вы используете (UDP, TCP и т. д.) самостоятельно;
  2. вам каким-то образом придется не допускать, чтобы стек IP и транспортных протоколов ядра обрабатывал эти пакеты;

и вы на самом деле не хотите этого делать.

(Обратите внимание, что под «повышенными привилегиями» я не обязательно подразумеваю «привилегии root»; CAP_NET_RAW привилегий должно быть достаточно. Однако, как я заметил, если вы пытаетесь заменить обычный доступ к сокету, вы не хотите использовать PF_PACKET сокеты. .)

person Community    schedule 01.03.2013
comment
Вы можете использовать этот интерфейс для отправки стандартных пакетов UDP (SOCK_DGRAM) см. здесь где режим — SOCK_RAW для необработанного интерфейса, в котором может быть захвачена информация на уровне канала, или SOCK_DGRAM для подготовленного интерфейса, где захват информации на уровне канала не поддерживается, а псевдозаголовок на уровне канала предоставляется ядром. - person charliehorse55; 02.03.2013
comment
Вы можете, но вам придется создать заголовок IP самостоятельно, а что касается получения стандартных пакетов UDP, если есть процесс, прослушивающий порт UDP, он получит эти пакеты, даже если вы используете сокет PF_PACKET, и если нет процесса, прослушивающего порт UDP, ядро ​​отправит сообщение ICMP Port Unreachable, даже если вы используете сокет PF_PACKET. package_mmap не отличается от обычных сокетов PF_PACKET и не является заменой для обычных сокетов PF_INET/PF_INET6. - person ; 02.03.2013

Хотя это на самом деле не отвечает на вопрос (поскольку речь идет конкретно о package_mmap), учитывая ваши параметры:

  1. Получение UDP-пакетов
  2. Хотите уменьшить системные вызовы, ничего больше.
  3. Желание использовать специфичные для Linux функции, но нет root-пользователя
  4. Возможности package_mmap на самом деле не нужны и не нужны.

Я бы рекомендовал вам полностью забыть о packet_mmap и вместо этого взглянуть на recvmmsg (обратите внимание на написание, а не на опечатку).

recvmmsg не требует специальных привилегий, он очень интуитивно понятен (никаких непонятных вещей, он работает точно так же, как readv) и позволяет вам получать много пакетов за один вызов, что значительно снижает нагрузку на системные вызовы.

person Damon    schedule 01.03.2013
comment
Интересно, посмотрю. Думаю, мне придется создать рабочий поток для вызова recvmmsg и поместить результат в кольцевой буфер. (Мне нужен кольцевой буфер для эффективной многопоточности) - person charliehorse55; 01.03.2013
comment
Можно, а можно просто убедиться, что есть что почитать во-первых, поэтому recvmmsg не будет блокироваться. Обычно это так же хорошо, как запускать дополнительный поток (но менее сложно). - person Damon; 01.03.2013
comment
Я думал об этом, но не вызовет ли это много споров, когда несколько потоков пытаются читать одновременно? Кроме того, один поток может в конечном итоге получить много пакетов одновременно и не оставить ни одного для других потоков. - person charliehorse55; 02.03.2013
comment
Почему вы должны получать в нескольких потоках в первую очередь? Одного потока вполне достаточно для приема всего, что идет по гигабитному или 10-гигабитному кабелю. Обычно у вас будет один поток, который ничего не делает, кроме как получает, и, возможно, другой поток (или еще несколько) обрабатывает данные, если вы хотите использовать параллелизм. Одновременное получение данных несколькими потоками не имеет преимущества в производительности и, вполне возможно, может быть медленнее (много переключений контекста). - person Damon; 02.03.2013
comment
Вот почему я говорил, что мне придется создать поток для чтения входящих пакетов в кольцевой буфер. - person charliehorse55; 03.03.2013