Подвисание при ARP-флуде

28 views
Skip to first unread message

er ty

unread,
Nov 23, 2017, 6:34:25 PM11/23/17
to uOS embedded
Здравствуйте!
Столкнулся с такой проблемой.

В сети находится большое количество устройств с серверной частью на базе UOS.

Перед подключением к устройствам, клиент (ПЭВМ) массово рассылает пачки ARP-запросов (10-15 за раз, каждую секунду) для получения адресов.

При отсуствии устройства клиент пытается переподключится.

При приеме пачки ARP-запросов, состоящей из 10-20 пакетов, устройство начинает увеличивать время ответа на запросы по TCP/ICMP.

Время ответа увеличивается до 3 секунд.

Тестировалось на различных платформах(AVR + ENC28J60, STM32F407 + ENC28J60, 1986ВЕ1Т, 1986ВЕ91Т + 5600ВГ1) и ветках дистрибутивов.

Грубо говоря сетевая подсистема устройств подвисает при ARP-флуде.

Есть ощущение, что накапливается огромное количество неотработанных пакетов в памяти.


Вылечилось временным костылем.


Файл netif.c:

buf_t *
netif_input
(netif_t *netif) {

 
struct _buf_t *p;

   
for (;;) { // крутимся пока не отработаем ВСЕ арпы

        p
= netif->interface->input (netif);

       
if (p && netif->arp) p = arp_input (netif, p); // если есть пакет передаем в arp_input. если нет пакетов выходим из netif_input
       
else return 0;

       
if (p) return p; // arp_input вернул указатель отдаем его остальным уровням
   
}
}



У кого какие мысли по этому поводу?

Serge V.

unread,
Nov 23, 2017, 6:39:37 PM11/23/17
to uOS embedded
В принципе логично, но "else return 0;" вызывает подозрение.

--Сергей

Александр Литягин

unread,
Nov 23, 2017, 11:48:46 PM11/23/17
to uOS embedded
А в чем логика?
10-15 пакетов/сек - это не нагрузка. Как может арп влиять на тсп?

Меня последняя строка смущает - 
if(p) return p;
а если не (р)? То функция без результата останется?

24 ноя 2017 г. 2:39 AM пользователь "Serge V." <serge.v...@gmail.com> написал:

--
Вы получили это сообщение, поскольку подписаны на группу "uOS embedded".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес uos-embedded+unsubscribe@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес uos-em...@googlegroups.com.
Чтобы зайти в группу, перейдите по ссылке https://groups.google.com/group/uos-embedded.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

er ty

unread,
Nov 24, 2017, 3:06:38 AM11/24/17
to uOS embedded

Реализация костыля была проведена на скорую руку конечно же:

p = netif->interface->input (netif); //возвращает p если есть пакеты, 0 если нет

if (p && netif->arp) p = arp_input (netif, p); // если netif->interface->input вернул р отдаем arp_input, если не веренул р, то вообще выходим (else return 0;) из netif_input.
                                               
//         то есть никаких пакетов для работы нет.
else return 0; // вышли из netif_input

if (p) return p; // из условия if (p...) p = arp_input (..); если пакеты были, и это были арпы, то arp_input их отработает и вернет 0,
                               
//     сответственно условие для возврата не выполнится if (p) return p; и мы снова перейдем в начало for (;;).



Раз в секунду прилетает примерно такая последовательность |ARP|ARP|ARP|ARP|ARP|ARP|ARP|IP|ARP| 1 секунда |ARP|ARP|ARP|ARP|ARP|ARP|ARP|IP|ARP| 1 секунда |.
Интервал в пачке между ARP минимально возможный.
Через debug_printf было обнаружено что количество принятых ARP-пакетов драйвером ethernet адаптера, не соответствует количеству вызовов функции arp_input.
При этом на устройство не посылалось ничего кроме ARP и IP-пакетов.
Для тестов использовался повторитель (HUB). Также устройство подключалось напрямую к ПК. Результат не изменяется.
При подключении через свич, пропускаются первые пачки ARP-запросов. Далее он(свич) их просто фильтрует.

Даже самый простой тест - пачка ARPов и утилита PING(без ключей). Проект собирается из examples, tcp-test. Результат пинг достигает 1-3 секунд.

10-15 пакетов/сек - действительно не нагрузка для микрокнтроллеров (1 MIPS на МГц) работающих на 80-160 МГц.

---------------------

if(p) return p;
а если не (р)? То функция без результата останется?
сели не (р), то дальше продолжит крутиться в for (;;). Там же бесконечный цикл.
--------------------

else return 0; можно заменить на конструкцию типа:

for (;;) {  

   
if (!(p = netif->interface->input (netif))) return 0; //пакетов нет! возвращаемся!
   
...
   
...
}

Масса вариантов как можно красиво переписать.

Александр Литягин

unread,
Nov 24, 2017, 1:32:03 PM11/24/17
to uOS embedded
Через debugprintf неполучится трассировать реальное время. Тем паче что у вас миниматьное время между пакетами. Если разве, будете по одному символу кидать на пакет. Может конечно фифо 4уарта даст и несколько символов бросать.
Я для отладки таких траблов встраивал журнал реального времени, только хардкором можно это размотать.

24 ноя 2017 г. 11:06 AM пользователь "er ty" <tye...@gmail.com> написал:
...

Александр Литягин

unread,
Nov 25, 2017, 5:51:58 AM11/25/17
to uOS embedded
Журнал можете посмотреть в buffers/rtlog_buf.h, специально для сетевого стеки пилил.

24 ноя 2017 г. 9:32 PM пользователь "Александр Литягин" <alexray...@gmail.com> написал:
Reply all
Reply to author
Forward
0 new messages