После полутора лет разработки состоялся выпуск проекта F-Stack 1.13, развивающего работающий в пространстве пользователя высокопроизводительный сетевой стек, основанный на фреймворке DPDK и TCP/IP стеке FreeBSD (F-Stack не привязан к FreeBSD и в качестве первичной платформы для применения рассматривает Linux). Проект используется в различных продуктах и сервисах Tencent, крупнейшей в Китае телекоммуникационной компании. Код распространяется под лицензией BSD. Поддерживается работа в Linux и FreeBSD...Подробнее: https://www.opennet.me/opennews/art.shtml?num=51884
Подождите-ка, подождите-ка... Вон та верхняя картинка, с 600-байтными пакетами - там решение на F-Stack скейлится линейно с ростом нагрузки, тогда как ядерный стэк выходит на предел производительности. Это что, получается, сетевой стэк FreeBSD после трансплантации на Linux настолько уделывает родной стэк Linux'а?
Дак мы вам об этом уже 30 лет рассказываем. а вы всё трындите про свои какие-то рынки, инвестиции и тому подобный бред
Не забывай что ядро делает ещо кучу нужного и не очень нужного кода/логики, но ты наверное не повериш так как сильно круто любиш фрю. В итоге посмотри такиеже тесты графики но уже на родной ФРЕ.
>Не забывай что ядро делает ещо кучу нужного и не очень нужного кода/логикиДа нет, судя по графику там просто где-то что-то лочится.
Дело не во фряшном стеке, а в DPDK.
> Дело не во фряшном стеке, а в DPDK.Во-во. Фряшный стек взяли чисто из соображений политкорректности, а так-то линуховый всяко дело лучше.
В каком месте самый бестолковый стек "Всяко лучше". Когда netgraph или что-то подобное с той-же легкостью прицеплять будете вместе с "сетевым ассемблером" тогда и будете трындеть про всяко лучше. А до тех пор самый отстой что есть в сетевом opensource это linux стек IP. Этож где это видано - транспортный и прикладной уровень скриптами фильтровать! ДИКАРИ!
дело не в большей производительности, а том что f-stack расположен полностью в пространстве пользователя. Это позволяет избавиться от лишних аллокаций и переключений контекста, а так как они зависят от числа пакетов, то наибольшая выгода будет достигаться в сценариях с кучей мелких пакетов. Что ты и видишь на графике.
Я конечно не иксперд, но думаю смысл именно в том, чтоб не терять производительность между юзерспейсным приложением и сетевой картой. В обычном случае тормоза появляются от гоняния юзерспейс<->ядро. Тут же приложения смогут напрямую ломиться к утсройству без переключений контекста.
Вот тебе идея, как уменьшить накладные расходы на переключение контекстов.Пишем простой модуль ядра, который открывает управляющий файл в /dev/batch_net_syscall или даже /proc/batch_net_syscall и принимает запросы в пакетном режиме (это вместо нового системного вызова). При записи в файл, ядру пачками передаются запросы на сетевые чтения/запись, причем как по UDP, так и TCP в формате типа sendmmsg (или типа того, как делает Linux AIO (io_submit), который также умеет работать с сетью, но делает это синхронно, или вообще в формате io_uring, который может вообще почти без системных вызовов принимать запросы, потому что весь обмен идет через кольцевой буфер, причем в обе стороны). Далее ядерный поток разгребает все еще не выполненные до конца запросы (новые и ранее полученные). Когда какие-то запросы завершились, управляющий файл batch_net_syscall становится доступным на чтение (и при чтении сообщает, какие запросы завершились). Таким способом можно реализовать работу в том числе и в режиме proactor (возможно, только так и получится, т.е. до завершения запроса буферы с данными трогать нельзя, с ними работает ядро). В случае пакетной обработки будет одно переключение на весь пакет, в случае обмена через кольцевые буферы (один для запросов, другой для ответов), когда есть незавершенные запросы можно просто добавлять в буфер новые без переключения контекста (а если запросов нет, то и нагрузки нет никакой, а значит, накладные расходы на переключение не имеют значения).
Как думаешь, почему так никто до сих пор не сделал? Ведь решение достаточно простое (не примитивное, но очень простое). Оно нужно только тем, кому не хватает стандартной производительности и горизонтальное масштабирование плохо работает, а значит, у них хватит ресурсов для написания такого модуля ядра (повторюсь, модуль довольно простой, не надо быть экспертом в ядре Linux, хватит LDD3 и статей из интернета). Вместо этого пишут решения с дублированием сетевых драйверов и сетевого стека целиком со всеми его заморочками... Ну, в общем делают решение раз в 100 сложнее.
И правда, имбецилы какие-то. Особенно в сравнении с анонимами оупеннета...
Всё равно потребуется копирование из user space в kernel space. Избавиться от этого в принципе нельзя. В Linux kernel уже добавляли такую возможность, а потом выпили потому, что без копирования никак.
F-Stack же не требует копирования.
Дополню, там где есть копирование там есть и выделение памяти, а выделение памяти это синхронная операция.
Здесь нету никакой проблемы копирования. Здесь мы видим убогий лям rps на полутора десятках ядер. Это обоссанных пол гига. Эти пол гига копируются 1/(50-100) секунды из/в память. Т.е. отсутствие копирование даст тебе 1% производительности. Слишком малая пропускная способность для того, что-бы копирования памяти на что-то кардинально влияло.Если там у тебя будет не убогих 5 гигабит, а в 10-100 раз больше - тогда профит уже будет заметен.
Дело не в чистом копировании, а в том что на каждый send() дёргается сискол, который переключает контекст и делает ещё пачку проверок.
Про накладные расходы на сискол даже школьнику известно. А вот про то, что все пакеты которые нужно отправить нужно скопировать в kernel space почему-то не часто задумываются. Сисколы можно дёргать параллельно, а память выделять для копирования можно только синхронно. Короче, учи мат.часть.
Сам учи.
Я zerocopy для отправки уже лет 5 юзаю, с момента выхода FreeBSD 10.
Там сделали так что shm можно делать полностью смапленый в память, но получать файловый дескриптор годный для передачи в sendfile().
У меня msd так работает: у него кольцевой буфер где лежит принятый TS поток лежит как раз в такой смапленой памяти, и когда кому то надо послать очередную порцию то дёргается sendfile() с нужным оффсетом и размером. И реально никаких копирований нет, ну кроме тех аргументов что в sendfile() передаются, что просто не существенно.В линуксах вроде аналогично, но делается файл в tmpfs.
У вас какая-то альтернативная память, раз её нельзя выделять параллельно.
Не потребуется.
Достаточно смапить память через mmap(), я сам так делал когда то для одной кастомной железки.
Ты наверно виндузятник или просто ламер.
Через mmap нельзя отобразить пакеты в кернел спейс, в кернел спейс нужно обязательно копировать т.к. есть неоднократно проверенный креш, при определённых условиях.
Как минимум слать можно без копирования через sendfile() из смапленного в память файла.Да, копировать наверное в большинстве случаев при приёме необходимо, но не из за крешей а из за того что требуется отрезать заголовки, делать дефрагментацию и тп.
Я тебе отвечу почему - потому что обезьяне нужны говносокеты. И в этом проблема. А сделать нормальное api не проблема. Просто кто его юзать будет?
> Как думаешь, почему так никто до сих пор не сделал? Ведь решение достаточно простое (не примитивное, но очень простое).Каким дураком надо быть, чтобы писать ядерный код там, где можно обойтись юзерспейсным? То есть, если бы всё было так просто, как ты описываешь, может быть в этом и имелся бы смысл, но в реальности ведь получится обычная задница: мы напишем модуль, пропишем протокол общения между модулем и юзерспейсом, но на следующей же день выяснится, что протокол не позволяет что-то там сделать эффективно. Мы изменим протокол допишем модуль. Через неделю ещё раз. Потом ещё. Ещё. И ещё. И так это будет продолжаться до тех пор, пока этот модуль не превратиться в кусок оверинжиниринга переплетённый с обратной совместимостью (потому что мы не каждый раз переписывали модуль, когда в этом возникала необходимость, лишь тогда когда не было возможности этого избежать посредством юзерспейсных костылей). Потом, подумав, мы добавим в ядро интерпретатор байткода, чтобы мы могли бы грузить в ядро процедурки, управляющие обработкой трафика. А потом всё наше приложение окажется в ядерном адресном пространстве. И ядро превратиться в дуршлаг. И вот тут, мы подумаем и вынесем стек TCP/IP в юзерспейс, оставив в ядре только самое необходимое.
Зачем эти сложности, если сразу можно вынести TCP/IP стек в юзерспейс?
>Каким дураком надо быть, чтобы писать ядерный код там, где можно обойтись юзерспейсным?Обязательно сообщи это вот этим ребятам tempesta-tech.com
Общались с этими ребятами. Ну как бы так - уровень их специалистов не очень впечатлил, явно пытались хвататься за контракты не имея полных знаний о предметной области.Кроме того - ребята открыли для себя socket filter из FreeBSD и теперь пиарятся этим знанием.
Просто интересно, socket filter из FreeBSD чем-то отличаются от такого же из Linux?
Да.
В фре их два:
- умеет ждать пока всё тело http запроса придёт, те до crlfcrlf и тольпо после сокет уходит в accept
- тоже самое только для полного dns запросаВ линуксе фильтр просто ждёт пока не придёт n байт.
главное позволяет сразу прочитать за sys call весь HTTP запрос.
Ну еще есть хороший API который позволяет из модуля дописать свой фильтр..
Чего Linux предоставить не может.
Да у фряхи под ядро кодить - сплошное удовольствие, там можно и своих ядерных модулей понаписать.
Проблема там не в самом стеке, а в api на говносокетах.Если просто. У тебя есть поток пакетов, которые приходят из сети. Там есть tcp-говна(протокол для веб-макак от веб-макак). Оно работает как говно, да и он и есть говно, но - не в этом проблема.
Весь этот поток пакетов распиливается на множество уже tcp-потоков. Далее всё это говно сливается в буфера сокетов. Далее уже в юзерспейсе у тебя есть идентификаторы этих сокетов, которые ты долбишь путём read/write.
Проблема именно в этой долбёжки, которая происходит из юзерспейса в кернелспейс и обратно. Это не вся проблема, но наиболее заметная её часть.
Что же делается тут. Поток пакетов сразу отдаётся юзерспейсу. И тут даже неважно как - главное то, что у меня вместо тысяч сисколов и копирований будут десятки.
А уже далее берётся тот самый стек говна на мусорных сокетах и запускается в юзерпейсе. Он так же пилить всё это говно на тысячи потоков/сокетов и веб-говно так же общается с ним.
Но теперь это происходит в юзерпейса и никакой коммуникации между ядром и юзерпейсом на каждое чтение/запись ненужно.
И так же очевидно, что если выкинуть это мусорное api для веб-макак(а ещё лучше выкинуть этот протокол говна), то все проблемы уйдут сами собою. Но веб-макак тогда ничего не сможет - как же она будет без мусорных сокетов.
z-copy вроде Линукс научился? или это опять только в FreeBSD ?
Уже была в ядре такая штука, но её выпилил в версии 3.15 или типа того. Нельзя сделать для Linux zero copy из user space в kernel space.
Как интересно, выше ты пишешь, что нет никакой проблемы в копировании, а тут пишешь - "главное то, что у меня вместо тысяч сисколов и копирований будут десятки". Выше тебе уже пояснили, что копирование это есть выделение памяти, синхронная операция и т.д. и т.п. Но написав это ты сам себе противоречишь.
Что это с тобой, шизофрения?
Смысл понятен, но ты хоть сравни - когда веб появился, а когда сокеты.
Согласно царю, всмемирное общество хттп-раст-скрипт-макак отправило агентов в прошлое, чтобы изобрести TCP и сокеты. А вообще, смысл с ним разговаривать, он же поехавший и не умеет в причинно-следственные связи.
Но зачем? Неужели нельзя просто взять и запилить новое API, без сокетов, исключительно через отображения в память, при этом разбирать пакеты по приложениям по-прежнему в ядре?
Ну так и нужно делать и даже написал это. Но у тебя есть миллионы обезьян, которые хотят и могут только жрать говно. Куда ты их денешь? Именно из-за них мы и живём в говне. Сектанты орут "хттп - круто", "говноскрипты - круто" и прочую чушь. Среди этих убогих мы и живём, но откуда нам взять столько сортиров? Ведь если завтра мы выкинем сокеты, хттп, говноскрипту, tcp и прочий мусор - все эти поломои пойдут на туда, к чему их привала природа - мыть сортиры/полы.К тому же, эта поделка и базируется на подобном api.
> Ну так и нужно делать и даже написал это. Но у тебя есть миллионы обезьян, которые хотят и могут только жрать говно. Куда ты их денешь?Вот только не надо. Нет никакой проблемы иметь сбоку сокет интерфейс, который будет работать по старой схеме для старых приложенией.
>Зачем эти сложности, если сразу можно вынести TCP/IP стек в юзерспейс?Позвольте, в чем глубокий смысл этой процедуры (кроме, разве что, легкости доступа к потрохам), чтобы выносить TCP/IP в юзерспейс? Процессору всё равно, какой код молотить - ядерный или юзерспейсный, и если в юзерспейсе реализовать все те же функции, что и в ядре, мы получим точно такую же производительность, что и в ядре.
Легкость "подкручивания" - согласен. Но часто ли надо "подкручивать" TCP/IP?
Вы говорите "оверинжиниринг", но полноценная юзерспейсная реализация TCP/IP будет точно таким же оверинжинирингом. От того, что вы вынесете код в юзерспейс, он не станет внезапно простым и лаконичным.
>>Зачем эти сложности, если сразу можно вынести TCP/IP стек в юзерспейс?
> Позвольте, в чем глубокий смысл этой процедуры (кроме, разве что, легкости доступа
> к потрохам), чтобы выносить TCP/IP в юзерспейс? Процессору всё равно, какой
> код молотить - ядерный или юзерспейсный, и если в юзерспейсе реализовать
> все те же функции, что и в ядре, мы получим точно
> такую же производительность, что и в ядре.Потому что вопрос немного в другом: выбор не между выносить TCP/IP в юзерспейс или не выносить, выбор между засовывать ли весь код (включая сюда и http сервер) в ядро, или выносить весь код в юзерспейс. Задача стоит в том, чтобы разграничительная линия сисколлов проходила бы не между кодом http-сервера и TCP/IP стеком, а где-нибудь в другом месте, где эту линию можно будет реже пересекать.
> Легкость "подкручивания" - согласен. Но часто ли надо "подкручивать" TCP/IP?
TCP/IP не надо часто подкручивать, но вот реализацию TCP/IP заточенную под какие-то оптимизационные параметры и использующуюся для различных задач -- придётся. Возможно её придётся подкручивать под каждое конкретное применение. Оптимизация она такая.
> Вы говорите "оверинжиниринг", но полноценная юзерспейсная реализация TCP/IP будет точно
> таким же оверинжинирингом. От того, что вы вынесете код в юзерспейс,
> он не станет внезапно простым и лаконичным.Оверинжиниринг -- это не просто количество кода, это скорее к тому, как много возможностей было заложено в код при проектировании, и как много из них оказалось востребовано. Дисбаланс между этими вещами либо приводит к костылестроению, вызванному тому, что библиотечный код неспособен решать задачи, которые он должен решать, либо этот дисбаланс приводит к оверинжинирингу, когда библиотечный код безумно сложен из-за того, что он рассчитан решать все задачи мира, в нём есть возможность подкрутить и настроить всё что угодно, в том числе и то, что никто никогда не подкручивает и не настраивает, но реально используется лишь часть этого. Скажем функция с двадцатью аргументами, из которых в 99 случаях из ста используются два первых, в остальные в 99 случаях передаются всякие значения типа 0, NULL, -1, nil и тп. Или безумная иерархия классов, из которых половина всегда создаётся дефолтным конструктором и никогда не меняется никем и ничем, несмотря на огромнейшие API позволяющие всё это настроить.
Вынос кода в юзерспейс позволяет более интересные способы взаимодействия между библиотечным кодом и клиентским. Не только сисколлы типа read/write, но скажем, итератор -- библиотека вполне может реализовать метод next, для перебора каких-либо сущностей, и этот метод может быть даже инлайн-функцией, если это надо. Библиотека может дать доступ к своей внутренней структуре и дать мне возможность либо читать её, либо даже менять -- может быть посредством непосредственной записи в поля, может быть посредством inline акцессоров, или может быть посредством сложных функций которые выполняют сложные действия. Это всё можно в юзерспейсе, это снимает кучу ограничений с разработчиков кода, это резко упрощает им задачу, и соответственно у них гораздо больше шансов получить _простой_ код, который с одной стороны не утонет в костылях, с другой стороны не будет на 90% неиспользуемым в реальности. Простой не в смысле количества строк кода, а в смысле того сколько потребуется времени, для того чтобы разобраться в этом коде и понять как этот код надо изменить, чтобы требуемым образом изменить поведение этого кода.
>Задача стоит в том, чтобы разграничительная линия сисколлов проходила бы не между кодом http-сервера и TCP/IP стеком, а где-нибудь в другом месте, где эту линию можно будет реже пересекать.Ну вынесете вы TCP/IP в юзерспейс - сисколы к ядру от этого магическим образом не исчезнут и меньше их не станет.
>как много возможностей было заложено в код при проектировании, и как много из них оказалось востребовано
Выше вы пишете: "на следующей же день выяснится, что протокол не позволяет что-то там сделать эффективно. Мы изменим протокол допишем модуль. Через неделю ещё раз. Потом ещё. Ещё. И ещё.". Как вы сами писали, возможности закладываются не от балды, а из-за необходимости делать что-то там эффективно, стало быть, эти функции востребованы.
С другой стороны, ну хорошо: выносим TCP/IP в юзерспейс, удаляем всякое "ненужное". Всё это приведет к тому, что в юзерспейсе будет зоопарк реализаций TCP/IP разной степени кривизны вместо одной эталонной реализации. Не кажется ли вам это еще большим оверинжинирингом и распылением сил?
Открытым остается и вопрос файрволинга в такой конфигурации.
>>Задача стоит в том, чтобы разграничительная линия сисколлов проходила бы не между кодом http-сервера и TCP/IP стеком, а где-нибудь в другом месте, где эту линию можно будет реже пересекать.
> Ну вынесете вы TCP/IP в юзерспейс - сисколы к ядру от этого
> магическим образом не исчезнут и меньше их не станет.Количество сисколлов уменьшится, причём вовсе не магическим образом.
>>как много возможностей было заложено в код при проектировании, и как много из них оказалось востребовано
> Выше вы пишете: "на следующей же день выяснится, что протокол не позволяет
> что-то там сделать эффективно. Мы изменим протокол допишем модуль. Через неделю
> ещё раз. Потом ещё. Ещё. И ещё.". Как вы сами писали,
> возможности закладываются не от балды, а из-за необходимости делать что-то там
> эффективно, стало быть, эти функции востребованы.Нет, на практике так бывает редко.
> С другой стороны, ну хорошо: выносим TCP/IP в юзерспейс, удаляем всякое "ненужное".
> Всё это приведет к тому, что в юзерспейсе будет зоопарк реализаций
> TCP/IP разной степени кривизны вместо одной эталонной реализации. Не кажется ли
> вам это еще большим оверинжинирингом и распылением сил?Распыление сил -- это миф. А почему это не оверинжиниринг я объяснил выше.
> Открытым остается и вопрос файрволинга в такой конфигурации.
Ой не знаю. Кто тебе сказал, что этот вопрос вообще стоял?
Помнится несколько лет назад в Facebook была вакансия системного разработчика Linux с хорошим знанием FreeBSD и в качестве целей его найма прямо в объявлении значилось "сделать сетевой стек Linux таким же хорошим, как во FreeBSD".
Как видно, китайские товарищи, отчаявишись, пошли путём его переноса в userspace... :-)
Ага, было такое: https://bsd-beta.slashdot.org/story/14/08/06/1731218/faceboo...
На счёт сетевого стека все претензии тому чуваку из параллельс который написал реализацию TCP/IP
А как же огромное комьюнити и вливающие миллиардами корпорации?
Хотел напомнить про рсапил, который придумали далеко не у нас,
но так вливают то - похоже за дыры, в каком нибудь TCP-IP,
а не за их устранение и тем более оптимизации
Там нетфликс давно уже поперписал.
Есть аналогичный порт линукс стека на dpdk и он также уделывает стек в ОС. И есть еще коммерческие стеки под DPDK, которые в свою очередь серьезно уделывают эти порты с FreeBSD или Linux.
И чего только китайцы потащили бсдшный стек в линукс, если линуксовый стек в dpdk и так торт. Наверное, фрибсд фаундейшн приплатила. Как уже когда-то майкрософту.
Вполне могли потому и потащить, чтобы в своём юзерспейсном софте иметь BSD-лицензию. Корпорасты GPL боятся когда надо и когда не надо
> Вполне могли потому и потащить, чтобы в своём юзерспейсном софте иметь BSD-лицензию.
> Корпорасты GPL боятся когда надо и когда не надоhttps://github.com/F-Stack/f-stack/blob/dev/LICENSE
> 1.DPDK
> BSD 3-Clause, Copyright(c) 2010-2017 Intel Corporation.All rights reserved.Ой?
> 8.Microthread framework
> GPL-2.0, Copyright (C) 2016 THL A29 Limited, a Tencent company.All rights reserved.
> Корпорасты GPL боятсяОга, поэтому вложились в разработку новой приблуды для линуха.
>Корпорасты GPL боятсяА так всё славно начиналось - да мы корпорастов в стойло поставим, да мы из них все сырцы выбъем, да наш ляликс будет цвести и пахнуть.
А на деле это привело лишь к тому, что корпорасты стали как огня бояться вляпаться в линукс, вместо этого вкладываясь в BSD, используя линукс лишь как запускатор приватных программ.
Всё правильно делают. Ибо нефиг копирастничать.
Лолшто? Корпорации написали и оплатили 90% кода ляликса, превратив в запускатор для своих программ.Много амазон вернул кода? Тесла? Гугл? ВМварь? БМВ? Китайцы?
Но все это "уделывание" происходит в рамках локальной сети/ЦОД, а в интернет рулит BBR (который недавно таки портировали в BSD) или еще лучше QUIC.
А потом вынесут всё ядро в юзерспейс и будет микроюзер ядро.
Так ведь уже лет 5 или 10 как ядро можно запускать в user space
можно то можно, только оно там еле шевелится
"еле шевелится" ???вообще то так работает жесткий RT на базе L4
Какой он тогда RT.. да, даже просто из UserSpace/Ring3...
Учи матчасть. RT не обязан шевелиться быстро, он обязан шевелиться с предсказуемой скоростью.
>сетевое взаимодействие в приложениях, применяя вместо сетевого стека операционной системы собственный сетевой стек, функционирующий в пространстве пользователя и напрямую работающий с сетевым оборудованием.Так это что получается, приложение должно от рута исполняться, чтобы иметь доступ к регистрам сетевой карты?
Нет, там требуется разрешение которое есть только у root. Root может дать эту привелегию любой учётке и эта превелигированная учётка будет иметь право использовать raw sockets, но в остальном она будет такой же не превелигированной учёткой, как и остальные юзеры.
дада, раз мы не умеем openvpn и прочие xlat в ядро... мы захр^W сделаем сетевой стек в юзерспейс. а ну навались!!!
в systemd еще не запихнули ?
Наверное единственное полезное что можно добавить в этого монстра ... Userspace.kerneld ...
Кто то может пояснить как DPDK работает с железом в обход ядра?
Регистры железа мапятся в адресное пространство процесса.
в ядре выполняется мини модуль - который представляет user land доступ к некоторому ring buffer.
+ события.
Этот ring - доступен как hugepages для всех - что уменьшает количество страниц требуемых для работы большими объемами данных.
Предоставлять доступ к адресному пространству ядра или работать из ядра с памятью в пространстве пользователя плохая практика, может грозить проблемами с безопастностью
вам шашечки или ехать?можно тупить пытаясь пропихать кучу трафика через page cache, а можно использовать раз выделенные буфера замасленные в userspace и иметь z-copy. Второй подход дает пропускную раз в 10-15 выше.
Так что вы уж решите что вам подходит.. хотя для админов Localhost это наверно не важно.
> Предоставлять доступ к адресному пространству ядра или работать из ядра с памятью в пространстве
> пользователя плохая практика, может грозить проблемами с безопастностьюА оно не делает ни того, ни другого, вообще-то. DPDK обычно запирает PCI, и не только, устройства за IOMMU посредством VFIO, так что никакое ядро в память пользователя не лезет, как и сам процесс в адресное пространство ядра. Один из немногих опциональных сервисов, который ядро предлагает DPDK процессу после того, как всё сконфигурировалось - это сообщать о прерываниях, генерируемых устройством для нечастых событий, типа link down/up.
посмотри плиз что такое VFIO - и посмотри как huge pages мапятся в дескрипторы у сетевухи (hint - то что там называют PMD - не является полным драйвером).
> посмотри плиз что такое VFIO - и посмотри как huge pages мапятся
> в дескрипторы у сетевухи (hint - то что там называют PMD
> - не является полным драйвером).Откройте сокровенное знание, что есть полный драйвер? А то я, написав несколько PMD для наших железок, в недоумении. По моему скромному разумению, то, что называетcя PMD - это именно полный драйвер для управления устройством. Кто-то его, собственно, обязан инициализировать и дёргать, это код в процессе, использующем DPDK и слинкованом с DPDK библиотеками, таком как VPP, F-Stack или какого-то из примеров. Принимает он, понимаете, пакетики из RX rings, запихивает их в TX rings, получает TX status обратно, обрабатывает link status-ы - какой магической субстанции ему не хватает для полноценности в глазах Анонима?
Насчёт как hugepages мапятся в дескрипторы я как бы знаю, сдаётся, как минимум не хуже вас, и у меня для вас сюрприз - точно так же, как и я ядре, с той только разницей, а что собственно выступает в качестве DMA адреса (IOVA). Обычно это либо либо собственно физический адрес (PHYS), либо вообше virtual address в процессе (VA) - это уж зависит от какой IOMMU, и какой режим поддерживается UIO драйвером, что диктует, как соответствующие области памяти процесса будут прописаны в IOMMU, и будет ли IOMMU использоваться вообще. Из предлагаемых vfio-pci, vfio-dpaa[2], uio_pci_generic и uio_idb все чуток разнятся. К примеру, прокси MSI и MSI-X прерываний поддерживает только vfio-pci, а uio_igb и uio_pci_generic могут только в INTx. Режим IOVA == VA могут только vfio-{dpaa2,vpp}, если IOMMU не выключен специально.
Учитывая вышесказанное, таки поделитесь, в какую область DPDK процесса лезет ядро, и в какую область ядра может несанционированно пробраться коварный DPDK process? Плиз.
Звучитит так что хотят сделать ненужными асики...
Не поддержки IPv6 и однопоточный. Это точно порт с FreeBSD ? :)
https://github.com/F-Stack/f-stack/tree/dev/freebsd/netinet6
а это что?
Давно не видел пакетов по 600 байт, типовая страница весит пару метров.
А вот для mqtt да вполне может быть.
Ну главный продукт у Tencent это QQ...
я не могу заставить его работать, может быть вы мне поможете ?
`#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <unistd.h>#include "ff_config.h"
#include "ff_api.h"
#include "ff_epoll.h"#define PORT 5672
#define SERVER "10.10.10.60"
#define MAXBUF 4096
#define MAX_EPOLL_EVENTS 64
int sockfd;
struct sockaddr_in dest;
char rbuf[MAXBUF];
void *wbuf;
size_t wbuf_size;
struct epoll_event events[MAX_EPOLL_EVENTS];
int i, n, epfd, num_ready;
struct epoll_event event;
int f_run = 1;int loop(void *arg)
{
/*---Wait for data---*/num_ready = ff_epoll_wait(epfd, events, MAX_EPOLL_EVENTS, -1 /*timeout*/);
if (num_ready == 0)
{
return -1;
}
printf("Number of events %d \n", num_ready);
for (i = 0; i < num_ready; i++)
{
if (events[i].events & EPOLLIN)
{
printf("Socket %d got some data\n", events[i].data.fd);
bzero(rbuf, MAXBUF);
n = ff_recv(sockfd, rbuf, sizeof(rbuf), 0);
printf("Readed from socket %d bytes \n", n);
printf("-= Data: =- \n");
for (i = 0; i < n; i++)
{
if ((rbuf[i] < 40) || (rbuf[i] > 126))
{
if (i != 0)
{
printf(",%u", (unsigned int)rbuf[i]);
}
else
{
printf("%u", (unsigned int)rbuf[i]);
}
}
else if (rbuf[i] == 206)
{
printf("----\n");
}
else
{
printf("%c", rbuf[i]);
}
}
printf(".\n-= Done =-\n");
}
if (events[i].events & EPOLLOUT)
{
n = ff_write(sockfd, wbuf, wbuf_size);
printf("Writed to socket %d bytes \n", n);
}
}
}
int main(int argc, char *argv[])
{
/*---Init F-Stack---*/
ff_init(argc, argv);
/*---Open socket for streaming---*/if ((sockfd = ff_socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
exit(errno);
}
int on = 1;
ff_ioctl(sockfd, FIONBIO, &on);
printf("Opend socket.\n");/*---Initialize server address/port struct---*/
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(PORT);
if (inet_pton(AF_INET, SERVER, &dest.sin_addr.s_addr) == 0)
{
perror(SERVER);
exit(errno);
}/*---Connect to server---*/
if (ff_connect(sockfd, (struct linux_sockaddr *)&dest, sizeof(dest)) != 0)
{
if (errno != EINPROGRESS)
{
perror("Connect ");
exit(errno);
}
}
sleep(1);
printf("Connected to socket.\n");/*---Add socket to epoll---*/
epfd = ff_epoll_create(1);event.events = EPOLLIN | EPOLLOUT;
event.data.fd = sockfd;
ff_epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);
printf("Initialized epoll to socket.\n");/*---Wait for socket connected---*/
ff_run(loop, NULL);
const char hello[] = {'A', 'M', 'Q', 'P', 0, 0, 9, 1};
wbuf_size = 8 ;
wbuf = (void *)realloc(wbuf, wbuf_size);
memcpy(wbuf, hello, wbuf_size);
// event.events &= ~EPOLLOUT;
printf("тут");
event.events |= EPOLLOUT;
ff_close(sockfd);
return 0;
}`в моей логике callback это то что вызывается в результате какого-то события, но после ff_run все. и ff_connect не конектится(с соединением все ок!).