#354 closed баг (fixed)
Не устанавливается IP адрес платы
Reported by: | san | Owned by: | alx |
---|---|---|---|
Priority: | высокий | Milestone: | 1 очередь |
Component: | any | Keywords: | |
Cc: |
Description
В Веб-интерфейсе платы отображается IP=192.168.1.53, однако команда ifconfig говорит что адрес не установлен.
root@comcerto:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:AD:C5:00:00:69 UP BROADCAST RUNNING MTU:1500 Metric:1 RX packets:1223615 errors:0 dropped:0 overruns:0 frame:0 TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:82931862 (79.0 MiB) TX bytes:468 (468.0 B) Interrupt:1 eth1 Link encap:Ethernet HWaddr 00:1A:1B:1C:1D:1E inet6 addr: fe80::21a:1bff:fe1c:1d1e/64 Scope:Link UP BROADCAST RUNNING NOARP MTU:1500 Metric:1 RX packets:236576 errors:0 dropped:0 overruns:0 frame:0 TX packets:2196 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:9920262 (9.4 MiB) TX bytes:78490 (76.6 KiB) Interrupt:1 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:15496 errors:0 dropped:0 overruns:0 frame:0 TX packets:15496 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1278264 (1.2 MiB) TX bytes:1278264 (1.2 MiB)
Содержимое лога платы:
root@comcerto:/# logread Nov 12 07:03:57 comcerto syslog.info syslogd started: BusyBox v1.18.5 Nov 12 07:13:03 comcerto daemon.info dnsmasq[369]: reading /tmp/resolv.conf.auto Nov 12 07:13:03 comcerto daemon.info dnsmasq[369]: using local addresses only for domain lan Nov 12 07:13:03 comcerto daemon.info dnsmasq[369]: using nameserver 8.8.8.8#53 Nov 13 05:37:44 comcerto daemon.info init: starting pid 259, tty '/dev/ttyS0': '/bin/ash --login' root@comcerto:/#
При записи адреса "вручную" (ifconfig eth0 192.168.1.53) адрес успешно устанавливается, однако при попытке сменить адрес через веб-интерфейс на другой, ifconfig по прежнему показывает .1.53.
Ревизия ПО 23 (VE-02)
Change History (8)
comment:1 by , 4 years ago
comment:2 by , 4 years ago
Включение режима DHCP и последующий возврат к статическим настройкам ничего не изменили, в логе сообщений об ошибках нет.
comment:3 by , 4 years ago
Обнаружены новые странности: в списке процессов отсутствует ntpclient, а при установке режима DHCP отсутствует udhcpc.
comment:4 by , 4 years ago
Попробую подвести предварительный итог (что выяснено на сегодняшний день).
Достоверно известно, что чтение/запись переменной .5.0 (адрес платы) происходит. Записываемый адрес попадает во внутреннюю переменную платы, из которой потом читается (в случае статической конфигурации).
Установлено, что флаг standalone_mode не установлен (по факту прихода трапов).
Сразу после записи нового адреса во внутреннюю переменную безусловно выполняется network_setup(). Установлено, что network_setup() действительно выполняется (путем установки невалидного значения адреса eth2 и последующего получения сообщения "poller.cpp:1286: invalid eth2 IP address: erere").
Установлено, что при записи в переменную .5.0 невалидного адреса (например "tratata") network_setup() выполняется, однако сообщения "invalid eth0 IP address written: tratata" в логе не появляется.
Между строкой poller.cpp:1286 и парсингом адреса "tratata" в переменной ipaddr, который должен был завершиться выводом в лог ошибки, есть только два места, в которых network_setup() могла завершиться:
if(ipaddr.empty()) return; if(dhcpclient_pid) { start_dhcp("no"); return; }
Первое условие заведомо не выполняется, так как мы знаем, что в ipaddr находится "tratata". Остается единственный правдоподобный вывод - выход из network_setup() происходит из-за того, что в переменной dhcpclient_pid почему-то не 0. Программа думает, что запущен клиент DHCP и пытается его завершить. В норме после заверения udhcpc должен придти сигнал SIGCHLD, по которому dhcpclient_pid обнулится и будет повторно вызвана network_setup().
follow-up: 7 comment:5 by , 4 years ago
Как и ожидалось, после перезапуска sip_ua адреса стали присваиваться.
По какой причине в dhcpclient_pid могло оказаться ненулевое значение при отсутствии процесса, остается только гадать...
В качестве решения проблемы можно периодически проверять реальное наличие процесса udhcpc и ntpclient, и если его нет, принимать соответствующие меры.
comment:7 by , 3 years ago
Replying to alx:
По какой причине в dhcpclient_pid могло оказаться ненулевое значение при отсутствии процесса, остается только гадать...
Загадка отсутствующего udhcpc при ненулевом значении dhcpclient_pid разгадана!
При старте DHCP клиента процесс sip_ua делает fork(), после чего родительский процесс присваивает PID порожденного процесса переменной dhcpclient_pid, а порожденный процесс делает execv() и, таким образом, превращается в udhcpc. Как показали исследования, первая часть действительно выполняется: fork() успешно порождает новый процесс, и родительский процесс присваивает его PID переменной dhcpclient_pid. А вот порожденный процесс с некоторой вероятностью по неизвестным причинам может не выполнить execv(). Такой процесс "застревает" в состоянии R (то есть готов к выполнению), но почему-то не получает процессорное время (показывает нулевую загрузку CPU).
В результате процесс "висит" и ничего не делает, при этом добавленная проверка существования процесса (см. comment:6) проходит успешно, так как процесс реально существует! Только не выполняется. Это похоже на какой-то ядерный баг...
Перед тем как выполнить execv() порожденный процесс выполнял ряд подготовительных действий:
- порождал новый сеанс;
- закрывал все открытые дескрипторы;
- разбивал команду запуска udhcpc на отдельные аргументы и составлял массив аргументов для передачи execv().
После того как я перенес последний пункт (составление массива аргументов) до вызова fork(), проблема воспроизводиться перестала: из 100 выполненных рестартов sip_ua не воспроизвелась ни разу, в то время как ранее воспроизводилась приблизительно один раз из 20.
Думаю, что можно оставить как есть, то есть "узаконить" перенесение формирования массива аргументов до вызова fork().
Существенное уточнение: плата сконфигурирована с использованием статического адреса. Это значит, что DHCP-клиент не используется, а веб-интерфейс отображает адрес, записанный в плату (значение, которое было записано в переменную .5.0), а не адрес, прочитанный с интерфейса eth0.
Тот факт, что из платы (из переменной .5.0) читается "192.168.1.53" означает, что значение адреса было успешно записано в плату. Логика далее следующая:
Мы же видим, что адрес eth0 не установлен, и при этом предупреждений в логе нет...
Я еще одну странность заметил: при применении настроек (п. 3 выше) если адрес интерфейса eth2 (LAN) пустой (а в нашем случае он пустой!), eth2 отключается (переводится в down), и в случае неудачи в лог пишется предупреждение "error bringing interface eth2 down". Но мы видим, что интерфейс eth2 - UP, и при этом в логе никаких предупреждений нет...