LINUX.ORG.RU

[kernel] Пересылка UDP минуя user space

 


0

0

Здравствуйте.
Есть необходимость пересылать UDP-пакеты внутри kernel space, не занимаясь их получением в user space`е и последующей отправкой на сокет. Нужно это для повышения производительности (избавляемся от копирования данных kernel -> user -> kernel).
Как мне представляется, нужно написать драйвер, которому задаются через ioctl параметры сокетов, портов, TOS, что-то ещё при желании. И этот драйвер должен заниматься тем, что будет пересылать пакеты с сокета на сокет внутри ядра.

Предполагаю, что для написания этой радости мне нужно ознакомиться с LDD разделом «Сетевые устройства» и ковырять ядро в части реализации сокетов и всего, что с ними связано. Может что ещё посмотреть присоветуете? Может даже какие-то готовые реализации уже есть?
Спасибо.

★★

может надо просто пару маршрутов прописать и пусть этот пакет маршрутизируется, можно даже его в iptables поправить немного или оно всё одно в user space пишется?

dimon555 ★★★★★
()

> Нужно это для повышения производительности (избавляемся от копирования данных kernel -> user -> kernel).

Там нет никакого копирования, передается вся страница из кернел-спейс в юзер-спейс. Затраты только на вызовы и переключение контекста. Вы бы хоть замеры сначала сделали, чем оптимизировать то, что с вероятностью в 0,9(9) оптимизировать не нужно.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

О! это интересно... но в моём случае копирование всё равно происходит. Я описал задачу в общем виде. Реально - есть устройство, которое генерит данные. Эти данные считываются с файла устройства, и тут же пишутся в сокет. Так вот нужно, чтобы драйвер этого устройства валил данные не в файл устройства, а в сокет напрямую. Вот мне и интересно - что там за интерфейс и где можно посмотреть пример подобной пересылки.

lv ★★
() автор топика
Ответ на: комментарий от bvvv

Почти оно, только:
Presently (Linux 2.6.9): in_fd, must correspond to a file which supports
mmap(2)-like operations (i.e., it cannot be a socket); and out_fd must
refer to a socket.

А мне надо не только с файла в сокет слать данные, но и наоборот. Хотя его код, думаю, посмотреть стоит.
Всё это будет крутиться на blackfin на 2.6.20.

lv ★★
() автор топика

Чесно говоря не понял что тебе нужно. Что значит «пересылка»? Может быть это можно сделать почитав man iptables?

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

> Чесно говоря не понял что тебе нужно.
Есть устройство, валящее трафик на свой chardev файл. Это устройство ещё и принимает траффик, который идёт ему на этот файл. Трафик постоянно внутри юзерспейса шлётся на/читается с сокет(/a). Нужно сделать так, чтобы весь трафик бежал миную юзерспейс.

> Может быть это можно сделать почитав man iptables?

Не уверен.

Сейчас читаю http://linux.opennet.ru/base/net/iptables_inside.txt.html
Оно как - актуально на сегодняшний день?

lv ★★
() автор топика
Ответ на: комментарий от lv

> Так вот нужно, чтобы драйвер этого устройства валил данные не в файл устройства, а в сокет напрямую.

Я не уверен, что это _на самом деле_ нужно, потому что для меня при такой постановке задачи остаётся загадкой такая вещь, как обработка ошибок. Особенно, если данные еще и планируется получать по UDP. Если соединение оборвется - то kernel panic?

Пиши драйвер для устройства. Точнее - два драйвера. На собственно устройство и обработчик UDP протокола.

А вообще, покопай в области init'а - там был чудный код и доки по созданию процессов прямо после загрузки, чуть ли не вшивая код в образ ядра. Если никаких других задач на ядре не будет исполняться, скорее всего это то, что тебе нужно _на самом деле_.

LamerOk ★★★★★
()
Ответ на: комментарий от lv

> Оно как - актуально на сегодняшний день?

В целом - да.

LamerOk ★★★★★
()
Ответ на: комментарий от lv

Т.е. ты уже сделал в юзерспейс и скорости не хватило?

true_admin ★★★★★
()
Ответ на: комментарий от LamerOk

> обработка ошибок. Особенно, если данные еще и планируется получать по UDP. Если соединение оборвется - то kernel panic?

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

> ..Если никаких других задач на ядре не будет исполняться..

Не - там ещё всякое есть.

lv ★★
() автор топика
Ответ на: комментарий от lv

> Нет пакетов, то и ловить нечего..

И соединение по новой ты открывать не будешь? Может ну его вообще, это устройство? )))

> там ещё всякое есть.


Тогда юзерспейс тебе в помощь - вся реальная работа будет по упаковке/распаковке данных в любом случае.

LamerOk ★★★★★
()
Ответ на: комментарий от lv

А может, драйвер этого устройства переделать из драйвера символьного устройства в драйвер сетевого интерфейса? И гонять данные туда-сюда стандартными способами.

tim239 ★★
()
Ответ на: комментарий от tim239

> А может, драйвер этого устройства переделать из драйвера символьного устройства в драйвер сетевого интерфейса?

:) Сейчас мне кажется, что это много лишней работы делать. В данный момент я представляю себе реализацию, как чтение буфера устройства, формирование UDP, и отправление skb на сетевое устройство hard_start_xmit(). Плюс к тому - повесить хук на NF_IP_LOCAL_IN и отправлять нужные пакеты в буфер устройства напрямую, а не в стек. Сейчас вопрос в том, как лучше UDP генерить - всё ручками или есть для этого какие-то вспомогательные функции.

lv ★★
() автор топика
Ответ на: комментарий от LamerOk

> Да. Если сокет на том конце схлопнеться - что делать?

Если честно, тоже не понимаю в чём проблема. Используется пересылка без установления соединения. То есть sendto(), recvfrom(). Ну схлопнулся там сокет, ну дропнет тот стек приходящие пакеты и всё...

lv ★★
() автор топика
Ответ на: комментарий от lv

Не, ну если постановка задачи допускает потери в передаче данных в любых объемах, то конечно никакой проблемы нет. Правда, при такой постановке становиться не очень понятным "повышение производительности ценой написания драйвера". ))

LamerOk ★★★★★
()
Ответ на: комментарий от lv

> всё ручками или есть для этого какие-то вспомогательные функции.

Есть в ядре все функции необходимые для обёртки данных в удп с выделением необходимой памяти и т.п.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

>Если сокет на том конце схлопнеться - что делать?

Похоже, ты не в курсе, что надо продолжать слать дальше. Рано или поздно кто-нибудь поднимется и снова будет слушать порт.

linuxfan
()

То есть ты хочешь, чтобы данные прямо с устройства уходили в сеть в виде UDP-пакетов, не попадая в userspace?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> То есть ты хочешь, чтобы данные прямо с устройства уходили в сеть в виде UDP-пакетов, не попадая в userspace?

Ага. Ну и чтобы из сети данные из нужных пакетов валились в устройство. Сейчас ищу чем UDP формировать.

lv ★★
() автор топика
Ответ на: комментарий от lv

>> То есть ты хочешь, чтобы данные прямо с устройства уходили в сеть в виде UDP-пакетов, не попадая в userspace?

Ага

И ты мерял хотя бы приблизтельно гипотетический выигрыш от того, что userspace не задействован, или просто хочешь, чтобы «было круто»? Потому что если твое устройство поддерживает DMA, отсылка UDP из ядра - кулхацкинг ради кулхацкинга.

Ну и чтобы из сети данные из нужных пакетов валились в устройство.

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

tailgunner ★★★★★
()
Ответ на: комментарий от lv

1) узнаёшь, как слать udp из user-space
2) идешь к соответствующему syscall в ядре
3) спускаясь по вызовам кернельных функций находишь наиболее подходящую тебе.

ЗЫ: есть такая древняя штука - lkcd. умеет слать дамп ядра по сети.
посмотри, как там в этом патче это реализовано.

xydo ★★
()
Ответ на: комментарий от lv

Ну тогда дорисуйте драйвер своего устройства. iptables/netfilter вам в этом деле пожалуй не поможет. Придется склепать кернел сокет и его слушать/писать

vasily_pupkin ★★★★★
()
Ответ на: комментарий от tailgunner

> И ты мерял хотя бы приблизтельно гипотетический выигрыш
Мерял - он есть. Да и доки на девайс говорят, что такой подход more efficient. Только драйвер, который это делает от них не получить почему-то - придётся собственноручно дорабатывать.

> Ты, конечно, помнишь, что UDP-датаграммы могут дублироваться и даже искажаться.


Насчёт искажения - чексумма мне в помощь. А насчёт дублирования... сетевой стек разве режет дублированные датаграммы? Я думал, что он валит в сокет всё валидное на него пришедщее.

lv ★★
() автор топика
Ответ на: комментарий от xydo

> 1) 2) 3)
Да - так и буду делать :)
> но, имхо, связать пару дискрипторов в user-space гораздо unix-way-нее

Да я бы и рад, но не получится так.

lv ★★
() автор топика
Ответ на: комментарий от vasily_pupkin

> Ну тогда дорисуйте драйвер своего устройства.
Да - так и сделаю.

> Придется склепать кернел сокет и его слушать/писать

Хмм.. а можно подробнее? Я думал, что можно хуком + генерацией UDP обойтись. Или вы это и имеете в виду под "кернел сокет"?

lv ★★
() автор топика
Ответ на: комментарий от lv

Ну вам же надо еще и что-то принимать. Плюс локал аутпут без сокета - нудная штука :]

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

> Наверное иногда стоит делать глупости для саморазвития ;)

Не-глупости тоже способствуют саморазвитию :).

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.