Opened 4 years ago

Closed 4 years ago

Last modified 3 years ago

#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 alx, 4 years ago

Существенное уточнение: плата сконфигурирована с использованием статического адреса. Это значит, что DHCP-клиент не используется, а веб-интерфейс отображает адрес, записанный в плату (значение, которое было записано в переменную .5.0), а не адрес, прочитанный с интерфейса eth0.

Тот факт, что из платы (из переменной .5.0) читается "192.168.1.53" означает, что значение адреса было успешно записано в плату. Логика далее следующая:

  1. если старый адрес не пустой, он удаляется из списка доменов repro;
  2. внутренней переменной платы присваивается новый адрес;
  3. применяются сетевые настройки:
    1. если адрес eth2 пуст (у нас пуст), eth2 переводится в down;
    2. если адрес eth0 не пуст (у нас не пуст), адрес устанавливается интерфейсу eth0, а в случае ошибки в лог выводится предупреждение;

Мы же видим, что адрес eth0 не установлен, и при этом предупреждений в логе нет...

Я еще одну странность заметил: при применении настроек (п. 3 выше) если адрес интерфейса eth2 (LAN) пустой (а в нашем случае он пустой!), eth2 отключается (переводится в down), и в случае неудачи в лог пишется предупреждение "error bringing interface eth2 down". Но мы видим, что интерфейс eth2 - UP, и при этом в логе никаких предупреждений нет...

comment:2 by alx, 4 years ago

Включение режима DHCP и последующий возврат к статическим настройкам ничего не изменили, в логе сообщений об ошибках нет.

comment:3 by alx, 4 years ago

Обнаружены новые странности: в списке процессов отсутствует ntpclient, а при установке режима DHCP отсутствует udhcpc.

comment:4 by alx, 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().

Version 0, edited 4 years ago by alx (next)

comment:5 by alx, 4 years ago

Как и ожидалось, после перезапуска sip_ua адреса стали присваиваться.

По какой причине в dhcpclient_pid могло оказаться ненулевое значение при отсутствии процесса, остается только гадать...

В качестве решения проблемы можно периодически проверять реальное наличие процесса udhcpc и ntpclient, и если его нет, принимать соответствующие меры.

comment:6 by alx, 4 years ago

Resolution: fixed
Status: newclosed

In 1793/sip_ua:

Добавлена периодическая проверка наличия процессов udhcpc (если требуется) и ntpclient.
Если вдруг обнаруживается, что процесс, который должен работать, отсутствует,
выполняется его запуск. Closes #354.

in reply to:  5 comment:7 by alx, 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().

comment:8 by alx, 3 years ago

In 1935/sip_ua:

Несущественная правка, устраняющая возможное зависание при запуске udhcpc. See #354.

Note: See TracTickets for help on using tickets.