Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работает драйвер сетевого устройства
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Linux
k000858
Портирую драйвер сетевого устройства (в общем ethernet драйвер) в OpenWRT. Драйвер успешно создает сетевой интерфейс и тд ондако ничего не работает. Не тикают даже счетчики в статистике. Сам драйвер выдран из SDK с 3.10.* ядром, в OpenWRT 4.4.14 ядро
Пока удалось выяснить что по каким то причинам не производится полинг интерфейса.

Сам интерфейс создается с помощью netif_napi_add, в аргументах которой указывается полинг функция. (которая, как выяснилось почему то не вызывается)

Кто сталкивался с подобным эффектом, или может у кого есть идейки куда капнУть?
winniethepooh
Цитата(k000858 @ May 18 2018, 12:32) *
Портирую драйвер сетевого устройства (в общем ethernet драйвер) в OpenWRT. Драйвер успешно создает сетевой интерфейс и тд ондако ничего не работает. Не тикают даже счетчики в статистике. Сам драйвер выдран из SDK с 3.10.* ядром, в OpenWRT 4.4.14 ядро
Пока удалось выяснить что по каким то причинам не производится полинг интерфейса.

Сам интерфейс создается с помощью netif_napi_add, в аргументах которой указывается полинг функция. (которая, как выяснилось почему то не вызывается)

Кто сталкивался с подобным эффектом, или может у кого есть идейки куда капнУть?


я вообще не специалист по сетевому стеку, но насколько я понимаю сетевое устройство дергает хардверным прерыванием
далее начинает работать драйвер сетевого ус-ва и для начала я бы посмотрел обрабатываются ли прерывания и что на входе у драйвера.
Полинг (если я не ошибаюсь запускают софтверные прерывания когда в кольцевом буфере появляются данные от сетевого устройства).
Вставить в код printf там где вызываются обработчики.
Простите если не въехал в "тему" я просто пытаюсь сказать как бы я действовал на вашем месте.
k000858
Цитата(winniethepooh @ May 18 2018, 16:45) *
я вообще не специалист по сетевому стеку, но насколько я понимаю сетевое устройство дергает хардверным прерыванием
далее начинает работать драйвер сетевого ус-ва и для начала я бы посмотрел обрабатываются ли прерывания и что на входе у драйвера.
Полинг (если я не ошибаюсь запускают софтверные прерывания когда в кольцевом буфере появляются данные от сетевого устройства).
Вставить в код printf там где вызываются обработчики.
Простите если не въехал в "тему" я просто пытаюсь сказать как бы я действовал на вашем месте.

Вы все верно описали - мой драйвер работает по NAPI модели:

Код
1. Драйвер включает NAPI, но изначально тот находится в неактивном состоянии.
2. Прибывает пакет, и сетевая карта напрямую отправляет его в память.
3. Сетевая карта генерирует IRQ посредством запуска обработчика прерываний в драйвере.
4. Драйвер будит подсистему NAPI с помощью SoftIRQ (подробнее об этом — ниже). Та начинает собирать пакеты, вызывая в отдельном треде исполнения (thread of execution) зарегистрированную драйвером функцию poll.
5. Драйвер должен отключить последующие генерирования прерываний сетевой картой. Это нужно для того, чтобы позволить подсистеме NAPI обрабатывать пакеты без помех со стороны устройства.
6. Когда вся работа выполнена, подсистема NAPI отключается, а генерирование прерываний устройством включается снова.
7. Цикл повторяется, начиная с пункта 2.


Прерываний нет (не только по прибытию входящих пакетов но и на изменение линка).
winniethepooh
Цитата(k000858 @ May 21 2018, 05:09) *
Вы все верно описали - мой драйвер работает по NAPI модели:

Код
1. Драйвер включает NAPI, но изначально тот находится в неактивном состоянии.
2. Прибывает пакет, и сетевая карта напрямую отправляет его в память.
3. Сетевая карта генерирует IRQ посредством запуска обработчика прерываний в драйвере.
4. Драйвер будит подсистему NAPI с помощью SoftIRQ (подробнее об этом — ниже). Та начинает собирать пакеты, вызывая в отдельном треде исполнения (thread of execution) зарегистрированную драйвером функцию poll.
5. Драйвер должен отключить последующие генерирования прерываний сетевой картой. Это нужно для того, чтобы позволить подсистеме NAPI обрабатывать пакеты без помех со стороны устройства.
6. Когда вся работа выполнена, подсистема NAPI отключается, а генерирование прерываний устройством включается снова.
7. Цикл повторяется, начиная с пункта 2.


Прерываний нет (не только по прибытию входящих пакетов но и на изменение линка).


непроинициализировано (неправвильно или неисправно) сетевое устройство, как бы самое простое предположение..
k000858
Цитата(winniethepooh @ May 21 2018, 10:02) *
непроинициализировано (неправвильно или неисправно) сетевое устройство, как бы самое простое предположение..

что могло так смениться в версиях ядра? сам драйвер прекрасно работает в 3.10.*
все подозрения на неработающее прерывание (нет реакции на изменение линка)

в начале работы драйвер даже не компилировался, например изза отсутствия в ядре IRQF_DISABLED (удален с 4.12.5 ядра).

winniethepooh
Цитата(k000858 @ May 21 2018, 08:40) *
что могло так смениться в версиях ядра? сам драйвер прекрасно работает в 3.10.*
все подозрения на неработающее прерывание (нет реакции на изменение линка)

в начале работы драйвер даже не компилировался, например изза отсутствия в ядре IRQF_DISABLED (удален с 4.12.5 ядра).



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

кажется была у linux возможность посмотреть на каких устройствах какие номера обработчиков зарегистрированы..
k000858
Цитата(winniethepooh @ May 21 2018, 11:07) *
почему старый драйвер не хочет работать с другим ядром я не могу предположить, но есть вероятно другие драйвера для нового ядра и можно посмотреть в чем отличия..,(изменился номер прерывания, не так регистрируется обработчик, не конфликтует ли с другим устройством т.к. общее прерывание)

кажется была у linux возможность посмотреть на каких устройствах какие номера обработчиков зарегистрированы..

сравниваю интегрируемый драйвер с имеющимися под новое ядро:
- в старом интегрируемом драйвере номер прерывания задан дифайном
Код
#define IRQ_ENET0    3     /* hardware interrupt #3, defined in ...

- в новом драйвере номер прерывания выбирается вызовом функции platform_get_irq

может тут какое то несоответствие? мне этот момент не очень понятен..
samike
Цитата(k000858 @ May 21 2018, 11:54) *
- в новом драйвере номер прерывания выбирается вызовом функции platform_get_irq

может тут какое то несоответствие? мне этот момент не очень понятен..


А как ваше интегрируемое сетевое устройство описано в Device tree? Как там сейчас задается прерывание?

Цитата(winniethepooh @ May 21 2018, 11:07) *
кажется была у linux возможность посмотреть на каких устройствах какие номера обработчиков зарегистрированы..


cat /proc/interrupts ?

winniethepooh
Цитата
cat /proc/interrupts ?


да оно
k000858
Цитата(samike @ May 22 2018, 10:16) *
А как ваше интегрируемое сетевое устройство описано в Device tree? Как там сейчас задается прерывание?



cat /proc/interrupts ?

Вроде как никак не описано. Сам драйвер вызывается

Код
module_init(ra2882eth_init);
module_exit(ra2882eth_cleanup_module);


samike
Цитата(k000858 @ May 22 2018, 11:01) *
Вроде как никак не описано. Сам драйвер вызывается

Код
module_init(ra2882eth_init);
module_exit(ra2882eth_cleanup_module);


Тогда выложите куда-нибудь посмотреть вашу ф-цию probe() из драйвера интегрируемого сетевого устройства (т.е. ф-цию инициализации драйвера).
Если есть подозрения на нерабочие прерывания, нужно посмотреть как они задаются на этапе инициализации - printk куда-нибудь поставить...
(если я конечно правильно понимаю проблему)
k000858
Цитата(samike @ May 22 2018, 12:16) *
Тогда выложите куда-нибудь посмотреть вашу ф-цию probe() из драйвера интегрируемого сетевого устройства (т.е. ф-цию инициализации драйвера).
Если есть подозрения на нерабочие прерывания, нужно посмотреть как они задаются на этапе инициализации - printk куда-нибудь поставить...
(если я конечно правильно понимаю проблему)

Проблема с прерываниями уже решена.

Что сделал:
- подсмотрел номера нужных мне прерываний через cat /proc/interrupts в ОС при работающем родном драйвере openWRT (который я пытаюсь заменить на интегрируемый).
- заменил номера прерываний на подсмотренные в дефайнах интегрируемого драйвера

Родной openwrt инициализируется через module_platform_driver, номера прерываний задаются в device tree и передаются в драйвер через MODULE_DEVICE_TABLE (если я все верно понимаю). В интегрируемом мной драйвере же номера прерываний заданы в дефайнах. Почему они отличаются..не понимаю. К слову, мое сетевое устройство это встроенный в SoC свитч, MT7621 SoC.

Прерывания на изменение линка и получение данных заработали. Так же заработала поллинг-функция. Дальше пакеты (в ОС) почему то не поступают, разбираюсь дальше.

samike
Цитата(k000858 @ May 22 2018, 12:22) *
Дальше пакеты (в ОС) почему то не поступают, разбираюсь дальше.


А как они поступают в ОС, в драйвере нужно вызвать netif_rx(skb) кажется?
Кстати, что у вас возвращает ф-ция netif_rx?
Я с NAPI моделью не работал, но думаю, что логика должна быть похожа:
При возникновении rx прерывания создаем skb из принятых данных:
Код
skb = netdev_alloc_skb(net_dev, len);

и далее что-то типа этого:
Код
data = skb_put(skb, len);
memcpy_fromio(data, addr, len);
netif_rx(skb);
k000858
Цитата(samike @ May 22 2018, 14:57) *
А как они поступают в ОС, в драйвере нужно вызвать netif_rx(skb) кажется?
Кстати, что у вас возвращает ф-ция netif_rx?
Я с NAPI моделью не работал, но думаю, что логика должна быть похожа:
При возникновении rx прерывания создаем skb из принятых данных:
Код
skb = netdev_alloc_skb(net_dev, len);

и далее что-то типа этого:
Код
data = skb_put(skb, len);
memcpy_fromio(data, addr, len);
netif_rx(skb);

да, что то вроде того. все верно описали вы.
в моем случае почему то не доходит до netif_rx, в драйвере куча ветвлений логики и препроцессора (#if)

разбираюсь.
winniethepooh
Цитата(k000858 @ May 23 2018, 11:22) *
да, что то вроде того. все верно описали вы.
в моем случае почему то не доходит до netif_rx, в драйвере куча ветвлений логики и препроцессора (#if)

разбираюсь.


В DMA входящие пакеты складывает?
drop для пакетов не происходит?
должна быть функция опроса типа RXDESC receive (RECEIVE DESCRIPTOR) читающая статусы
имеющихся дескрипторов пакетов на предмет передачи их наверх (netif_rx)
есть выходные данные у этой функции?
k000858
В моем случае вместо netif_rx выполняется netif_receive_skb (т.к. используется метод NAPI), функция возвращает в части случаев NET_RX_SUCCESS, в части случаев NET_RX_DROP, что говорит о том, что половина пакетов дропается.

При этом счетчик принятых пакетов в свойствах соединения растет. Так же растет и счетчик отправленных пакетов, однако входящих пакетов на ПК от устройства нет (соединение с ПК прямое).
Так же похоже после определенного количества принятых пакетов устройство перестает их принимать, во всяком случае счетчик принятых пакетов перестает расти. Такое ощущение что в систему пакеты поступают из драйвера, но не разгребаются там, занимаются всю доступную память, после чего устройство перестает отправлять пакеты в систему. может такое быть? какие могут быть причины?
winniethepooh
Цитата(k000858 @ May 24 2018, 06:47) *
В моем случае вместо netif_rx выполняется netif_receive_skb (т.к. используется метод NAPI), функция возвращает в части случаев NET_RX_SUCCESS, в части случаев NET_RX_DROP, что говорит о том, что половина пакетов дропается.

При этом счетчик принятых пакетов в свойствах соединения растет. Так же растет и счетчик отправленных пакетов, однако входящих пакетов на ПК от устройства нет (соединение с ПК прямое).
Так же похоже после определенного количества принятых пакетов устройство перестает их принимать, во всяком случае счетчик принятых пакетов перестает расти. Такое ощущение что в систему пакеты поступают из драйвера, но не разгребаются там, занимаются всю доступную память, после чего устройство перестает отправлять пакеты в систему. может такое быть? какие могут быть причины?


сбрасывать пакеты сетевое устройство может по причине отсутствия свободных дескрипторов.
попробуйте изменить кол-во дескрипторов, например
#define DEF_RXDESC_NUM (100 вместо 4 если память позволяет..)
если все пакеты теряются на нижнем уровне то это должно помочь.
k000858
Цитата(winniethepooh @ May 24 2018, 11:34) *
сбрасывать пакеты сетевое устройство может по причине отсутствия свободных дескрипторов.
попробуйте изменить кол-во дескрипторов, например
#define DEF_RXDESC_NUM (100 вместо 4 если память позволяет..)
если все пакеты теряются на нижнем уровне то это должно помочь.

попробую увеличить. правда вряд ли это поможет, большая часть пакетов все же удачно принимается, однако счетчик Rx0 = 0.

При том само устройство тоже отправляет пакеты (запрос DHCP), и этот запрос я вижу в программе DHCP сервер (мак точно устройства), но счетчик полученных пакетов на ПК 0. Как так??? ПО верхнего уровня пакет получает (DHCP запрос) а в свойствах сетевого соединения количество полученных пакетов не растет...

добавлено:

поправка - счетчик Rx на устройство растет в cat /proc/net/dev но не растет в ifconfig
Rx на ПК от устройства так же работает, вижу пакеты и в сниффере, но счетчик пакетов в винде не растет.

то есть у этих 2х эффектов одна причина.

пакеты - DHCP: запросы от устройства к ПК, затем ответ от ПК устройству и последующий повторный запрос (так по кругу) потому что ответ от ПК попал в систему устройства (netif_receive_skb NET_RX_SUCCESS) но система этот пакет не переварила.
winniethepooh
Цитата(k000858 @ May 24 2018, 09:04) *
поправка - счетчик Rx на устройство растет в cat /proc/net/dev но не растет в ifconfig
Rx на ПК от устройства так же работает, вижу пакеты и в сниффере, но счетчик пакетов в винде не растет.

то есть у этих 2х эффектов одна причина.

пакеты - DHCP: запросы от устройства к ПК, затем ответ от ПК устройству и последующий повторный запрос (так по кругу) потому что ответ от ПК попал в систему устройства (netif_receive_skb NET_RX_SUCCESS) но система этот пакет не переварила.


да это интересно, что то в пакетах делает их невидимыми для ОС?
может можно сравнить с пакетами от другой системы..
k000858
распарсив sk_buff полученного пакета и сравнив его с аналогичным в родном драйвере openWRT, выяснил следующее:
- интегрируемый драйвер отправляет в ядро sk_buff без mac и ip заголовках, то есть skb->data начинается с UDP заголовка (при получении ответа DHCP). В родном драйвере skb->data начинается с протокола (0x0800 IP) и ip заголовка. Осталось научить драйвер дорисовывать ip заголовок с протоколом
winniethepooh
Цитата(k000858 @ May 28 2018, 06:14) *
распарсив sk_buff полученного пакета и сравнив его с аналогичным в родном драйвере openWRT, выяснил следующее:
- интегрируемый драйвер отправляет в ядро sk_buff без mac и ip заголовках, то есть skb->data начинается с UDP заголовка (при получении ответа DHCP). В родном драйвере skb->data начинается с протокола (0x0800 IP) и ip заголовка. Осталось научить драйвер дорисовывать ip заголовок с протоколом

вставлять заголовки может как ядра так и сетевое устройство..
k000858
Больше волнует вопрос: при получении пакета, должен ли содержаться заголовок IP протокола в sk_buff->data при передаче его в ядро из драйвера?
winniethepooh
Цитата(k000858 @ May 28 2018, 10:41) *
Больше волнует вопрос: при получении пакета, должен ли содержаться заголовок IP протокола в sk_buff->data при передаче его в ядро из драйвера?

если я не ошибаюсь, сетевое устройство может убрать ip заголовок из пакета(зависит от настоек NIC).
k000858
По делу есть кое какие продвижения: счетчик Rx уже щёлкает. Проблема была в отсутствии vlan тэгирования трафика. Теперь каждый полученный пакет тэгируется, за счет этого попадает в интерфейс. правда пока не тот. судя по всему пакеты, полученные по wlan'у, попадают в eth0.1 вместо eth0.2.
k000858
В общем победил настройки встроенного в SoC свитча и 802.1Q vlan тэггирование: wan работает, lan'ы работают, даже мост более менее работает. но с лагами - похоже на потери.

По видимому причина в netif_receive_skb = -1

В каких случаях может такое происходить? Какому флагу соответствует -1 (1 = NET_RX_DROP).
winniethepooh
Цитата(k000858 @ Jun 7 2018, 09:09) *
В общем победил настройки встроенного в SoC свитча и 802.1Q vlan тэггирование: wan работает, lan'ы работают, даже мост более менее работает. но с лагами - похоже на потери.

По видимому причина в netif_receive_skb = -1

В каких случаях может такое происходить? Какому флагу соответствует -1 (1 = NET_RX_DROP).


посмотрите https://people.cs.clemson.edu/~westall/853/notes/
k000858
В общем драйвер успешно интегрирован, Lan'ы работают, Wan работает, трафик по мосту бежит.
Однако вылезла новая проблема: при тесте пропускной способности портов (трафик Wan -> Lan для использования NAT'а) драйвер нагружает систему до 99%, при этом скорость всего ~300Mbt/s (порты гигабитные). При этом родной драйвер openWRT выжимает гигабит, нагрузка на проц ~80% (хардварный нат не активирован). С чем может быть связан такой эффект?
winniethepooh
Цитата(k000858 @ Jun 14 2018, 04:51) *
В общем драйвер успешно интегрирован, Lan'ы работают, Wan работает, трафик по мосту бежит.
Однако вылезла новая проблема: при тесте пропускной способности портов (трафик Wan -> Lan для использования NAT'а) драйвер нагружает систему до 99%, при этом скорость всего ~300Mbt/s (порты гигабитные). При этом родной драйвер openWRT выжимает гигабит, нагрузка на проц ~80% (хардварный нат не активирован). С чем может быть связан такой эффект?


почему вы думаете драйвер нагружает а не сокет например?
k000858
Цитата(winniethepooh @ Jun 14 2018, 14:51) *
почему вы думаете драйвер нагружает а не сокет например?


Цитата(k000858 @ Jun 14 2018, 07:51) *
При этом родной драйвер openWRT выжимает гигабит, нагрузка на проц ~80% (хардварный нат не активирован)


тест проводится 1 в 1 с родным драйвером openwrt и мной интегрированным
winniethepooh
Цитата(k000858 @ Jun 14 2018, 12:17) *
тест проводится 1 в 1 с родным драйвером openwrt и мной интегрированным


ничего не знаю про тест openwrt, но сомневаюсь что он может показать в каком слое стека застревают пакеты.
k000858
Цитата(winniethepooh @ Jun 14 2018, 16:26) *
ничего не знаю про тест openwrt, но сомневаюсь что он может показать в каком слое стека застревают пакеты.

самый банальный тест пропускной способности с помощью iperf (v3.13), трафик из Lan'а в Wan (хардварного NAT'а нет).
При этом родной драйвер пропускает ~ гигабит, но загружает ЦПУ на 80%, мой драйвер пропускает лишь ~300Мбит/с, упираясь в 100% загрузку ЦПУ. очевидно что он выдал бы гигабит, если б хватило производительность ЦПУ.
Думаю сокет тут непричем, сам драйвер менее производительный. Возможно какая то его настройка (считай - дефайн или ключ компиляции) так влияет.

Повторюсь, драйвер работает по можели napi. Может есть мысли на что может тратиться процессорное время?
winniethepooh
Цитата(k000858 @ Jun 15 2018, 04:27) *
самый банальный тест пропускной способности с помощью iperf (v3.13), трафик из Lan'а в Wan (хардварного NAT'а нет).
При этом родной драйвер пропускает ~ гигабит, но загружает ЦПУ на 80%, мой драйвер пропускает лишь ~300Мбит/с, упираясь в 100% загрузку ЦПУ. очевидно что он выдал бы гигабит, если б хватило производительность ЦПУ.
Думаю сокет тут непричем, сам драйвер менее производительный. Возможно какая то его настройка (считай - дефайн или ключ компиляции) так влияет.

Повторюсь, драйвер работает по можели napi. Может есть мысли на что может тратиться процессорное время?

логика работы драйвера построена так что бы не отвлекать проц(используя dma разместить пакеты. ну вы должны это знать сами..)
у меня тоже проблема с медленной обработкой пакетов, я думаю это в уровне между стеком и пользовательским приложением(обработка совтовых прерываний, переключение из режима ядра в режим пользователя). я потратил много времени просматривая движение пакетов вверх по стеку и видел что они передаются без задержки. На уровне где расположены сокеты перестал работат printk и посмотреть где точно происходит задержка и потеря пакетов не удалось.
я предполагаю учитывая тяжеловесность слоя сокетов (я использую ARM Cortex-M3 144 Мгц, 16Мб ОЗУ uClinux) что задержка происходит в этом слое.
k000858
Как в драйвере задать битовую маску CPU, которая после создания соединения прописывается в rps_cpus (/sys/class/net/<device>/queues/<rx-queue>/rps_cpus
) ???
Olej
Цитата(k000858 @ Jun 15 2018, 06:27) *
Повторюсь, драйвер работает по можели napi. Может есть мысли на что может тратиться процессорное время?

В модели NAPI есть такой важный параметр как счётчик числа сетевых пакетов, при приёме меньше которого драйвер возвращается из режима программного пулинга и переходимт в режим ожидания прерываний. Поиграйтесь с этим параметром.

P.S. Может подскажет какую мелочь, из об ласти сетевых драйверов или модулей фильтров сетевых протоколов вот этот текст: Практикум по Linux Kernel.
Ну и Сетевое программирование в Linux - здесь о стыке сокетных буферов в ядре с сокетами простанства пользователя.
k000858
Цитата(Olej @ Jul 1 2018, 14:19) *
В модели NAPI есть такой важный параметр как счётчик числа сетевых пакетов, при приёме меньше которого драйвер возвращается из режима программного пулинга и переходимт в режим ожидания прерываний. Поиграйтесь с этим параметром.

P.S. Может подскажет какую мелочь, из об ласти сетевых драйверов или модулей фильтров сетевых протоколов вот этот текст: Практикум по Linux Kernel.
Ну и Сетевое программирование в Linux - здесь о стыке сокетных буферов в ядре с сокетами простанства пользователя.

благодарю за пинок в возможно верном направлении smile3046.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.