Перейти к содержимому
Калькуляторы

DHCP сервер с поддержкой SQL Написан. Нужны добровольцы-тестеры.

Упал через 6 часов с лишкой после перезапуска. Версия 0.1.а.4
Эх, незадача. Сделаю сегодня себе тестовый стенд на 1000+ псевдоюзеров и буду мучить сервер пока не упадёт. А может вообще свой кэш напишу, что-то не вижу я с ходу где там вообще может быть бага.

Кстати - те странные ошибки ещё появлялись? Но вообще раз он по прежнему падает при работе с кэшом - наверное оттуда и ошибки эти лезли.

 

Изменения:

  1. Удалено автоматическое заполнение поля 'Server IP' в заголовке DHCP пакета. Если необходимо - можно выдать эту информацию из БД.
Это опция №54?

Нет, это по прежнему заполняется по дефолту IP адресом интерфеса на котором получен запрос. Не заполняется теперь именно поле в заголовке.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кстати - те странные ошибки ещё появлялись? Но вообще раз он по прежнему падает при работе с кэшом - наверное оттуда и ошибки эти лезли.
Только эти:

# cat db2dhcp.log | grep ERROR
2011-03-13 09:09:27 [30617:1211110656] ERROR: Can't delete node from cache: FF:FF:FF:FF:FF:FF/172.16.15.152
2011-03-13 09:11:10 [30617:1211110400] ERROR: Can't delete node from cache: FF:FF:FF:FF:FF:FF/172.16.15.152

ХЗ куда делись те ошибки, ведь я только перезапустил сервер с опцией d.

Может версию 0.1.а.5 собрать таки с -g3 -O0?

Изменено пользователем Voronok

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Только эти:

# cat db2dhcp.log | grep ERROR
2011-03-13 09:09:27 [30617:1211110656] ERROR: Can't delete node from cache: FF:FF:FF:FF:FF:FF/172.16.15.152
2011-03-13 09:11:10 [30617:1211110400] ERROR: Can't delete node from cache: FF:FF:FF:FF:FF:FF/172.16.15.152

ХЗ куда делись те ошибки, ведь я только перезапустил сервер с опцией d.

Да в общем-то эти ошибки тоже не лучше, подозреваю что у них одни и те же корни и то какие будут ошибки зависит так сказать "от того как фишка ляжет". Тоже непонятно откуда они берутся, адреса абсолютно безумные. Что-то крепко не так с кэшом.

 

Может версию 0.1.а.5 собрать таки с -g3 -O0?
Ну давай, и под valgrind'ом запусти. Как упадёт - пришлёшь лог-файл.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Voronok, когда снова грохнется (а он наверное грохнется всё же) - можешь запустить с отключенным кэшированием? (DHCPCacheTTL = 0)

Очень хочется понять - бага действительно в кэше или что-то где-то в другом месте не правильно работает и повреждает данные кэша из-за чего и происходит сегфолт. Если второй случай - то скорее всего отключение кэша ничего толком не даст и через какое-то время всё равно процесс рухнет. Если же будет работать стабильно (хотя и сильнее нагружать БД), то видимо придётся ещё раз перековырять кэш, может даже отказаться от штатных бинарных деревьев и по своему написать.

В любом случае, будет интересно посмотреть вывод gdb на core дамп файл от процесса. Сделать надо так:

$ gdb /path/to/db2dhcp -c /path/to/core.dump
*** тут всякая мишура, на всякий случай лучше тоже скопировать ***
> bt <enter> - самое важное то что будет после этого.

 

[-Alt-], отлично! Кстати на сколько я понимаю - у вас кэширование выключено. Тем лучше, будет проверкой версии о бажности именно кэша.

 

Сейчас изо всех сил пытаюсь уронить демона - создал в БД 2048 псевдоклиентов с разными MAC адресами и запустил процесс получения IP адресов от них через dhcdrop в 8 потоков. В итоге получилось порядка 50 DHCP запросов в секунду (и соответственно столько же ответов), сервер работает уже несколько часов, написал мне более пол гига логов, регулярно чистит кэш (за раз удаляя примерно 70 узлов) и при этом упорно не желает падать. Подозреваю это от того что синтетический тест не реализует всех возможных ситуаций- например DHCPINFORM/DHCPRELEASE сообщений и общего "шума" в сети который тоже может несколько повлиять на работу. В общем - пока подожду ваших результатов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

На ночь не стану запускать, хочется выспаться. Утром запущу, днем буду следить. Кстати, в последний раз, я .core файл не нашел, хотя искал даже поиском.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну как, у кого-нибудь есть какие-нибудь плохие или хорошие новости?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вчера у нас перетрубации были, сервер не трогал.

Сейчас запустил с отключенным кэширпованием, посмотрим.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Работает 9 часов, тьфу-тьфу-тьфу. :)

 

USER    PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
dhcpd 42676  0.0  0.1 10892  2408  ??  S    10:00AM   0:00.01 /usr/local/sbin/db2dhcp -dc /usr/local/etc/db2dhcp.cong em1
...
dhcpd 42676  0.0  0.2 11916  3912  ??  S    10:00AM   0:23.62 /usr/local/sbin/db2dhcp -dc /usr/local/etc/db2dhcp.cong em1

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Voronok, спасибо. Похоже что действительно дело в кэше, у -Alt проработал нормально почти двое суток и не падал пока он сам его не потушил. Правда я так и не могу понять что же делаю не так со стандартными функциями работы с деревьями. Наверное какая-нибудь очередная недокументированная фича... Похоже что придётся самому полностью писать механизм кэширования.

 

PS Внёс небольшие правки в код, на функционал ни как не влияет но функция подсчёта контрольной суммы на некоторых компиляторах выдавала warning'и потому код не собирался (из-за установленной опции -Werror). Теперь должно собираться везде. Версию оставил ту же.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

У меня, с отключенным кэшированием, работает уже 26 часов.

 

USER    PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
dhcpd 42676  0.0  0.3 13964  5572  ??  S    Tue10AM   1:00.42 /usr/local/sbin/db2dhcp -dc /usr/local/etc/db2dhcp.cong em1

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Есть такой вопрос: Допустим имеется брас(с точки зрения dhcp является релеем), на котором есть 2 пула(1.0.0.0/24 gw 1.0.0.1 и 1.0.1.0 gw 1.0.1.1), есть лупбэк браса 1.1.1.1. В силу ряда причин есть необходимость слать dhcp-пакеты с лупбэка(т.е. ip.src=1.1.1.1, но giaddr=1.0.0.1(для первого пула) и 1.0.1.1(для второго пула)). Куда db2dhcp будет возвращаться пакеты?(на giaddr или ip.src?).

Собирать такой макет и провярить долго, поэтому спрашиваю.

 

Для isc dhcpd3.0 это проблема решается патчем из вложения.

patch_server__03_reply_to_client_ip.patch.zip

Изменено пользователем s.lobanov

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

* 2. Попробовать сделать аллокатор памяти на манер nginx'а - не факт что надо. Главное проверить что бы не тёк.

Сделайте проще:

каждый поток обрабатывает 1 запрос от начала и до конца, тогда можно смело использовать статический буфферы хоть со стёка потока хоть выделенные с кучи при старте потока.

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

У нгникса сильно другая ситуация, равняться на него не стоит, в данном вопросе.

 

 

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

В случае переполнения всё равно ничего не изменит.

 

 

Насчёт падения при включённом кеше:

dhcp_cache_find

попробуйте вместо cache_rdlock(); лочить на рв

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

 

cmp_nodes

проверьте что хвадрес там из дхцп пакета а не эзернет заголовка.

 

 

некоторая оптимизация:

void dhcp_cache_flush_old(void)
{
    time_t tm_now = time(NULL);

    if(cache_last_flush + CACHE_FLUSH_PERIOD > tm_now)
    {
        return;
    }
    cache_wrlock();

    cache_now = tm_now;
    cache_last_flush = cache_now;

 

 

 

По работе с сетью:

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

/usr/src/sys/net

/usr/src/sys/netinet

 

по арп:

вроде дхцп сервер должен пинг слать на адрес перед выдачей, а потом клиенту адрес выдавать, а клиент арпом проверять адрес и слать деклайн в случае чего, впрочем не вчитывался в этот момент.

У вас не проверяется в пришедшем пакете длинны хвлен и плен, да и вообще ничего.

У фряхи есть в заголовочниках макросы для правильного сбора и разбора, с учётом длинны. Можно и забить, если работать только под эзернет, только длину проверять при получении.

 

 

что касается кусков от для винды:

корректная инициализация:

__inline DWORD SocketsInitialize()
{
    DWORD dwRetErrorCode;
    WSADATA wsaData;

    if ((dwRetErrorCode=WSAStartup(MAKEWORD(1,1),&wsaData))==NO_ERROR)
    {// version 1.1 OK
        WSACleanup();
        
        dwRetErrorCode=WSAStartup(wsaData.wHighVersion,&wsaData);
    }
return(dwRetErrorCode);
}

 

Получение текстового описания ошибки по коду:

DWORD dwErrorCode....
WCHAR szErrDescription[1024];
        
szErrDescription[FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrorCode, 0, szErrDescription, 1000, NULL) - 2] = 0;

 

 

to_cidr - считает биты, не обращает внимание что между 1 может быть 0

(у меня тоже самое на перле)

 

 

parse_dhcp_message - делает не все проверки принятого дхцп(?) пакета:

message_len - не должен быть меньше 236 (размер буттп заголовка + кука + по идее хотя бы одна опция)

htype == HTYPE_ETHER && hlen == 6 (семёрка шлёт некоторые запросы которые этим фильтруются)

наличие куки (может и есть, не смотрел подфункции)

потом, если есть опция DHCP_SERVER_IDENTIFIER то её содержимое должно соответствовать тому что сервер отдаёт в этой опции иначе пакет не для этого сервера.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

У нгникса сильно другая ситуация, равняться на него не стоит, в данном вопросе.

Ну в общем-то "на манер" это не равно "точно так же" ;) Имеется ввиду интерфейс аллокатора, а не внутренняя реализаци.

 

Сделайте проще:

каждый поток обрабатывает 1 запрос от начала и до конца, тогда можно смело использовать статический буфферы хоть со стёка потока хоть выделенные с кучи при старте потока.

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

В случае переполнения всё равно ничего не изменит.

Если бы всё было так просто - ни кто не городил бы мультипоточного приложения ;)

Очередь тут вовсе не для защиты от переполнения. Очередь служит для асинхронной работы потоков слушающих интерфейсы и потоков работающих с БД. Узлы в неё добавляют потоки-"слушатели" интерфейсов, а разбирают очередь - потоки работающие с БД. Сделано так потому что запросы к БД в общем случае в API разных СУБД синхронны и блокируют поток пока не будет получен результат из базы. Рассказать чем это чревато при медленной работе БД и попытках выполнять эти запросы в том же потоке что слушает интерфейс?

В случае с очередью и отдельными потоками работающими с БД несколько залипших запросов (а такое бывает на нагруженных серверах) не заблокируют насмерть сервер, и значение это можно поставить достаточно большим. На многоядерной БД - очень выручит.

 

Насчёт падения при включённом кеше:

dhcp_cache_find

попробуйте вместо cache_rdlock(); лочить на рв

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

rd он на то и rd что бы можно было делать много вхождений в один участок, а не ждать когда другой поток там что-то сделает. Не надо трактором грядки пахать.

Отключить очистку и ждать когда процесс опухнет и будет убит по перееданию памятью? Тогда можно вообще не пробовать искать утечки памяти - кэш сам по себе будет одной большой утечкой :)

Включить реже - значит будет падать но не через несколько часов, а через несколько дней например.

Это всё не решения а костыли, неприемлемо.

 

Если не пойму в чём дело то лучше попробую RB Tree от MIT.

 

cmp_nodes

проверьте что хвадрес там из дхцп пакета а не эзернет заголовка.

Вот это кстати очень полезное замечание объясняющее ситуацию с адресами FF:FF:FF:FF:FF:FF в кэше! Там именно адрес заголовка, получилось так потому что изначально код (ещё когда-то очень давно) писался без использования relay агента и в принципе эти значения были эквивалентны, что конечно же верно совсем не всегда. А потом кэш был набросан быстро за один-два вечера и получился ляп. :( Широковещательный адрес в кэше при таком раскладе может оказаться если от локального клиента (без релея) пришло сообщение с установленным флагом Broadcast. Честно говоря мне теперь самому не совсем понятно как кэш умудрялся правильно работать при использовании relay.

 

некоторая оптимизация:
А как вам такой сценарий развития событий?

void dhcp_cache_flush_old(void)
{
    time_t tm_now = time(NULL);

    if(cache_last_flush + CACHE_FLUSH_PERIOD > tm_now)
    {
        return;
    }
              /* В этом месте поток А вошедший в функцию, проверивший условие и решивший что ему надо чистить кэш
                  останавливается планировщиком не успев заблокировать кэш и процессор переключается на поток Б. 
                  Поток Б тоже входит в выполнение этой функции, проверят условие, видит что оно не верно и нужно чистить кэш.
                  Блокирует кэш и начинает его чистить.
                  После чего тоже останавливается где-то в середине зачистки по переключению например на поток В. 
                  После чего управление переходит к потоку А, который просыпается и... Блокируется на вызове cache_wrlock() т.к. её уже
                  выполнил поток Б ныне спящий и по прежнему блокирующий кэш. После чего Б пробуждается, дочищает кэш, снимает блокировку.
                  В итоге поток А опять получает управление, радостно входит в блокировку кэша на запись и пытается почистить только что очищенный кэш.
                  В это время все остальные потоки работающие с кэшом будут ждать пока поток А выполнит уже не нужную операцию зачистки кэша. 
                  */
    cache_wrlock();

    cache_now = tm_now;
    cache_last_flush = cache_now;

Потому сделано так, а не иначе.

 

По работе с сетью:

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

/usr/src/sys/net

/usr/src/sys/netinet

Например потому что в разных системах эти файлы могут называться немного по разному, как и структуры в них. Да, это можно вылечить при помощи autoconf. Только вот есть проблема - в некоторых ОС этих файлов нет вообще ;)
по арп:

вроде дхцп сервер должен пинг слать на адрес перед выдачей, а потом клиенту адрес выдавать, а клиент арпом проверять адрес и слать деклайн в случае чего

Не совсем так. В RFC написано что сервер должен проверить то что адрес свободен например через ICMP echo request. Но вовсе не обязательно при помощи его. Учитывая что Windows по дефолту старается это заблокировать (как и большинство фаерволлов под неё) - проверка ARP'ом более уместна. Конечно она не реализуема при использовании relay. По возможности допишу проверку через ICMP в случае использования relay, но честно говоря это почти ничего не даст.

 

У фряхи есть в заголовочниках макросы для правильного сбора и разбора, с учётом длинны. Можно и забить, если работать только под эзернет, только длину проверять при получении.
Вообще не знаю есть-ли смысл писать под что-то отличное от Ethernet, много об этом думал. Хотя для приличия стоит сделать проверку. Брать проверки из FreeBSD либо откуда-то ещё не вижу смысла т.к. они абсолютно примитивны и их реализация - вопрос наличия у меня свободного времени.

 

что касается кусков от для винды:

корректная инициализация:

Да, согласен, там весьма убогий кусок кода и я знаю как делать правильно. Но сделано так потому что "лишь бы работало". Последние версии в виндах вообще не пробовал собирать (PG библиотеки лень ставить), буду собирать когда доведу до ума весь задуманный функционал.
to_cidr - считает биты, не обращает внимание что между 1 может быть 0
Да, именно так. И об этом я тоже знаю. А вы - представляете себе _нормальные_ сетевые маски у которых может быть 0 в середине?

 

У вас не проверяется в пришедшем пакете длинны хвлен и плен, да и вообще ничего.
parse_dhcp_message - делает не все проверки принятого дхцп(?) пакета:...
Верно замечено - местами вообще ничего не проверяется. Вы даже можете создать переменную в конфигурации со смещением в 100к и длинной в 1 Мб и сервер её съест, после чего вполне вероятно упадёт при обработке запроса.

Ещё раз отсылаю вас в первое сообщение этого топика, в котором написано что это очень тестовый код. А так же в раздел "Планируемые доработки" где написано что сервер должен быть приведён в соответствие с требованиями RFC. Сейчас интересно оттестировать базовый (и самый нужный 99% потенциальных пользователей) функционал и убедиться что программа ведёт себя адекватно. Как видите - ряд явных неадекватностей уже успешно выпилен, похоже осталось только с кэшом разобраться. После чего можно будет добавить несколько запрошенных фич (благо они простые), остановить добавление функционала и доводить его до лоска и блеска штудируя в одном окне код, а в другом RFC.

 

Спасибо за подсказку про кэш, но на будущее - предлагаю подобные беседы переносить в e-mail или какой-нибудь IM что-ли, кроме обнаружения явных и 100%ных багов. А то у нас длинный и малоинформативный для большинства читающих тред получается. Всё что найдёте - ваше :) Т.е. будет опубликовано вместе со следующей версией.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

tcpdump -i vlan500 -nvvves0 port 67 and host 10.254.0.77
tcpdump: listening on vlan500, link-type EN10MB (Ethernet), capture size 65535 bytes
03:30:20.465288 00:1e:58:70:86:c0 > 00:1b:21:86:a5:66, ethertype IPv4 (0x0800), length 362: (tos 0xfc, ttl 128, id 58210, offset 0, flags [none], proto UDP (17), length 348)
    10.254.0.77.68 > 10.254.0.1.67: [udp sum ok] BOOTP/DHCP, Request from 00:22:15:f1:4c:c3, length 320, hops 1, xid 0xd53ff78d, Flags [none] (0x0000)
          Gateway-IP 10.254.0.77
          Client-Ethernet-Address 00:22:15:f1:4c:c3
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Discover
            NOAUTO Option 116, length 1: Y
            Client-ID Option 61, length 7: ether 00:22:15:f1:4c:c3
            Hostname Option 12, length 15: "microsof-563b37"
            Vendor-Class Option 60, length 8: "MSFT 5.0"
            Parameter-Request Option 55, length 11:
              Subnet-Mask, Domain-Name, Default-Gateway, Domain-Name-Server
              Netbios-Name-Server, Netbios-Node, Netbios-Scope, Router-Discovery
              Static-Route, Classless-Static-Route-Microsoft, Vendor-Option
            Vendor-Option Option 43, length 2: 220.0
            Agent-Information Option 82, length 18:
              Circuit-ID SubOption 1, length 6: ^@^D^@^J^@^F
              Remote-ID SubOption 2, length 8: ^@^F^@^^XpM-^FM-@
            END Option 255, length 0
03:30:21.289484 00:1b:21:86:a5:66 > 00:1e:58:70:86:c0, ethertype IPv4 (0x0800), length 378: (tos 0x10, ttl 64, id 37075, offset 0, flags [none], proto UDP (17), length 364)
    10.254.0.1.67 > 10.254.0.77.67: [udp sum ok] BOOTP/DHCP, Reply, length 336, xid 0xd53ff78d, Flags [none] (0x0000)
          Your-IP 46.44.16.245
          Gateway-IP 10.254.0.77
          Client-Ethernet-Address 00:22:15:f1:4c:c3
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Offer
            Subnet-Mask Option 1, length 4: 255.255.248.0
            Default-Gateway Option 3, length 4: 46.44.16.1
            Domain-Name-Server Option 6, length 12: 192.168.10.1,192.168.10.2,62.140.229.3
            Lease-Time Option 51, length 4: 14400
            NTP Option 42, length 8: 192.168.10.1,192.168.10.2
            RN Option 58, length 4: 7200
            RB Option 59, length 4: 13800
            TFTP Option 66, length 10: "10.254.0.1"
            Server-ID Option 54, length 4: 10.254.0.1
            Agent-Information Option 82, length 18:
              Circuit-ID SubOption 1, length 6: ^@^D^@^J^@^F
              Remote-ID SubOption 2, length 8: ^@^F^@^^XpM-^FM-@
            END Option 255, length 0
03:30:21.294812 00:1e:58:70:86:c0 > 00:1b:21:86:a5:66, ethertype IPv4 (0x0800), length 393: (tos 0xfc, ttl 128, id 58216, offset 0, flags [none], proto UDP (17), length 379)
    10.254.0.77.68 > 10.254.0.1.67: [udp sum ok] BOOTP/DHCP, Request from 00:22:15:f1:4c:c3, length 351, hops 1, xid 0xd53ff78d, Flags [none] (0x0000)
          Gateway-IP 10.254.0.77
          Client-Ethernet-Address 00:22:15:f1:4c:c3
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Request
            Client-ID Option 61, length 7: ether 00:22:15:f1:4c:c3
            Requested-IP Option 50, length 4: 46.44.16.245
            Server-ID Option 54, length 4: 10.254.0.1
            Hostname Option 12, length 15: "microsof-563b37"
            FQDN Option 81, length 19: "microsof-563b37."
            Vendor-Class Option 60, length 8: "MSFT 5.0"
            Parameter-Request Option 55, length 11:
              Subnet-Mask, Domain-Name, Default-Gateway, Domain-Name-Server
              Netbios-Name-Server, Netbios-Node, Netbios-Scope, Router-Discovery
              Static-Route, Classless-Static-Route-Microsoft, Vendor-Option
            Vendor-Option Option 43, length 3: 220.1.0
            Agent-Information Option 82, length 18:
              Circuit-ID SubOption 1, length 6: ^@^D^@^J^@^F
              Remote-ID SubOption 2, length 8: ^@^F^@^^XpM-^FM-@
            END Option 255, length 0
03:30:21.319477 00:1b:21:86:a5:66 > 00:1e:58:70:86:c0, ethertype IPv4 (0x0800), length 312: (tos 0x10, ttl 64, id 14527, offset 0, flags [none], proto UDP (17), length 298)
    10.254.0.1.67 > 10.254.0.77.67: [udp sum ok] BOOTP/DHCP, Reply, length 270, xid 0xd53ff78d, Flags [none] (0x0000)
          Server-IP 10.254.0.1
          Gateway-IP 10.254.0.77
          Client-Ethernet-Address 00:22:15:f1:4c:c3
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: NACK
            Server-ID Option 54, length 4: 10.254.0.1
            Agent-Information Option 82, length 18:
              Circuit-ID SubOption 1, length 6: ^@^D^@^J^@^F
              Remote-ID SubOption 2, length 8: ^@^F^@^^XpM-^FM-@
            END Option 255, length 0
03:30:22.324434 00:1e:58:70:86:c0 > 00:1b:21:86:a5:66, ethertype IPv4 (0x0800), length 362: (tos 0xfc, ttl 128, id 58222, offset 0, flags [none], proto UDP (17), length 348)

 

2011-03-17 03:32:08 [45849:1090562752] Sending DHCPNAK (6) to 00:22:15:F1:4C:C3/0.0.0.0 via 10.254.0.1 (relay 10.254.0.77)
2011-03-17 03:32:09 [45849:1090562752] Got DHCPDISCOVER (1) message from client 00:22:15:F1:4C:C3 on vlan500/10.254.0.1 (relay 10.254.0.77)
2011-03-17 03:32:10 [45849:1090562752] Sending DHCPOFFER (2) to 00:22:15:F1:4C:C3/46.44.16.243 via 10.254.0.1 (relay 10.254.0.77)
2011-03-17 03:32:10 [45849:1090562752] Got DHCPREQUEST (3) message from client 00:22:15:F1:4C:C3 on vlan500/10.254.0.1 (relay 10.254.0.77)
2011-03-17 03:32:10 [45849:1090562752] Sending DHCPNAK (6) to 00:22:15:F1:4C:C3/0.0.0.0 via 10.254.0.1 (relay 10.254.0.77)

 

Не понятно почему 0.0.0.0 Requested-IP Option 50, length 4: 46.44.16.245

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Есть такой вопрос: Допустим имеется брас(с точки зрения dhcp является релеем), на котором есть 2 пула(1.0.0.0/24 gw 1.0.0.1 и 1.0.1.0 gw 1.0.1.1), есть лупбэк браса 1.1.1.1. В силу ряда причин есть необходимость слать dhcp-пакеты с лупбэка(т.е. ip.src=1.1.1.1, но giaddr=1.0.0.1(для первого пула) и 1.0.1.1(для второго пула)). Куда db2dhcp будет возвращаться пакеты?(на giaddr или ip.src?).
На IP адрес указанный в giaddr не зависимо от IP адреса с которого пришёл пакет. Ethernet адрес разумеется будет использован тот с которого получен пакет.

 

Новая версия: http://netpatch.ru/projects/db2dhcp/db2dhcp-0.1.a.6.tar.bz2

Изменения:

  1. Изменения в работе кэша - переделана функция сравнения и поиска кэшированных ответов.
  2. Устранён мелкий баг позволяющий дважды два раза добавить запрос в очередь от одного и того же клиента.
  3. Добавлено отладочного вывода при работе с кэшом. Если будут продолжаться проблемы - надеюсь поможет.

Был замечен какой-то баг при расчёте udp checksum (valgrind ругнулся, но ничего не упало), в итоге в ответе клиенту улетело что-то неправильное и он его не смог обработать. Случается похоже крайне редко. Буду разбираться.

 

PS Что-то плохо работает голова уже, эта версия могла получиться более бажной чем предыдущая ;) Возможно багу с подсчётом udp checksum сейчас добавил. Но проверить надо, и без кэша, и особенно - с кэшом.

 

PPS [-Alt-] 0.0.0.0 потому что DHCPNAK. А вот почему DHCPNAK исходя из лога понять сложно, по дампу вроде всё правильно, надо в код смотреть. Выше ни каких строчек по этому поводу не было? Проблема проявляется с данным клиентом постоянно? Уже нет сил разбираться сейчас...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если бы всё было так просто - ни кто не городил бы мультипоточного приложения ;)

Очередь тут вовсе не для защиты от переполнения. Очередь служит для асинхронной работы потоков слушающих интерфейсы и потоков работающих с БД. Узлы в неё добавляют потоки-"слушатели" интерфейсов, а разбирают очередь - потоки работающие с БД. Сделано так потому что запросы к БД в общем случае в API разных СУБД синхронны и блокируют поток пока не будет получен результат из базы. Рассказать чем это чревато при медленной работе БД и попытках выполнять эти запросы в том же потоке что слушает интерфейс?

В случае с очередью и отдельными потоками работающими с БД несколько залипших запросов (а такое бывает на нагруженных серверах) не заблокируют насмерть сервер, и значение это можно поставить достаточно большим. На многоядерной БД - очень выручит.

Покуда взаимодействие с базой идёт через сетевое АПИ, его можно было организовать асинхронно, кабы не деффекты при проектировании этих самых апи работы с базой - достаточно чтобы они только формировали и рагребали а отправляло/получало приложение.

Соотвественно заюзав kqueque или аналог можно сколько угодно запросов обрабатывать одновременно асинхронно хоть в одном потоке.

У меня решение в прерле проще: все потоки делают полный цикл обработки: принимают пакет с сокета, арзбирают, лезут в базу, шлют ответ и опять снова.

Работать с кучей интерфейсов можно попробовать через селект читать в потоках с кучи прибиндиных сокетов.

 

 

rd он на то и rd что бы можно было делать много вхождений в один участок, а не ждать когда другой поток там что-то сделает. Не надо трактором грядки пахать.

Отключить очистку и ждать когда процесс опухнет и будет убит по перееданию памятью? Тогда можно вообще не пробовать искать утечки памяти - кэш сам по себе будет одной большой утечкой :)

На время поиска бага, не на совсем.

Чтобы понять из за очистки он или где то ещё.

 

 

 

Честно говоря мне теперь самому не совсем понятно как кэш умудрялся правильно работать при использовании relay.
Там бы совсем правильно сделать - это брать клиент идентифир из опций, если нет то из дхцп пакета хваддр.

В поздних рфк написано что в клиент идентифир в опциях должно писатся DUD которое у клиента должно быть одинкого для в4 и в6 дхцп клиентов, и длинна там больше, чем у хваддр.

 

Я думал сделатьу себя кеш по проще: время хранения 10-30 сек, идентификация по хваадр и хид, чтобы после дискавера на регвест можно было ответить и в случае чего на информ, а дальше уже по обстоятельствам. Другой вариант ставить время жизни в кеше чуть больше листайм, но тогда теряем оперативное изменение настроек в клиенте при их изменении в базе, но обращения к базе фантастически падают.

 

 

 

Не совсем так. В RFC написано что сервер должен проверить то что адрес свободен например через ICMP echo request.
Я забил на это. Просто добавил деклайн обработку, пусть клиент проверяет. Так серверу и быстрее и проще.

 

 

Вообще не знаю есть-ли смысл писать под что-то отличное от Ethernet, много об этом думал. Хотя для приличия стоит сделать проверку. Брать проверки из FreeBSD либо откуда-то ещё не вижу смысла т.к. они абсолютно примитивны и их реализация - вопрос наличия у меня свободного времени.
Во фряхе до сих пор не проверяется длина хваддр, паддр кое как добавили, 4 месяц мнутся не могут мой патч добавить.

 

 

Да, именно так. И об этом я тоже знаю. А вы - представляете себе _нормальные_ сетевые маски у которых может быть 0 в середине?
Не уверен что все пользователи будут грамотными.

 

 

Верно замечено - местами вообще ничего не проверяется.
Что там юзер напишет в конфиге не так страшно, первая волна обычно грамотные, вторая копипастит с первых :)

Вот что падает с сети - может привести к ступору.

Про проверку что пакет предназначен именно этому дхцп серверу по полю дхцп_сервер_ид я понял только когда запустил второй %)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

По логам только это, по кругу, дисковер-оффер-рекуест-нак, проблема конкретно с этим клиентом, ну и еще несколько таких же выловились, чем конкретно они отличаются, пока не понимаю, но у них точно нет роутеров, обычная винда.

 

PPS [-Alt-] 0.0.0.0 потому что DHCPNAK. А вот почему DHCPNAK исходя из лога понять сложно, по дампу вроде всё правильно, надо в код смотреть. Выше ни каких строчек по этому поводу не было? Проблема проявляется с данным клиентом постоянно? Уже нет сил разбираться сейчас...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Покуда взаимодействие с базой идёт через сетевое АПИ, его можно было организовать асинхронно, кабы не деффекты при проектировании этих самых апи работы с базой - достаточно чтобы они только формировали и рагребали а отправляло/получало приложение.
Вот оно так и сделано. Тем методом которым мне это видится разумным. Не вижу резона делать иначе.
Соотвественно заюзав kqueque или аналог можно сколько угодно запросов обрабатывать одновременно асинхронно хоть в одном потоке.
Очень ОС зависимо, придётся под каждую ОС свой код писать, при чём не самый тривиальный. Оставлено на далёкое и счастливое коммунистическое будущее.
У меня решение в прерле проще: все потоки делают полный цикл обработки: принимают пакет с сокета, арзбирают, лезут в базу, шлют ответ и опять снова.
Я уже описал в чём проблемы подобного подхода.
Работать с кучей интерфейсов можно попробовать через селект читать в потоках с кучи прибиндиных сокетов.
Перед тем как давать такие советы - не плохо бы почитать документацию на libpcap ;) Не все ОС имеют возможность использования select'образных функций с pcap сокетами.

Только не надо предлагать отказываться от использования libpcap. Сейчас заботы о портировании в нативный код для конкретной ОС на плечах libpcap и её разработчиков, велосипедировать не собираюсь. Да и опять же, как показывает жизненный опыт - код использующий select (и подобное) становится сложнее для понимания и отладки при весьма слабом (в пределах нескольких процентов) выигрыше по ресурсам/скорости. В данном случае скорость практически не важна и от выигранных долей миллисекунд мы ничего не получим - это не hi-load продукт предназначенный для обработки десятков килоRPS (как nginx например).

 

Чтобы понять из за очистки он или где то ещё.
Не очень понимаю как это может помочь. Искать багу надо в условиях максимально приближённых к реальным.

 

 

Там бы совсем правильно сделать - это брать клиент идентифир из опций, если нет то из дхцп пакета хваддр.

В поздних рфк написано что в клиент идентифир в опциях должно писатся DUD которое у клиента должно быть одинкого для в4 и в6 дхцп клиентов, и длинна там больше, чем у хваддр.

Может быть. Только наверное имелось ввиду DUID. Но в принципе то что есть сейчас должно работать нормально не зависимо от версии клиента (если я ночью не налажал в коде :) ).

 

Я думал сделатьу себя кеш по проще: время хранения 10-30 сек, идентификация по хваадр и хид
Такой кэш будет работать только для первого DHCPREQUEST от данного клиента. Следующие DHCPREQUEST генерируются с другим xid.

 

Я забил на это. Просто добавил деклайн обработку, пусть клиент проверяет. Так серверу и быстрее и проще.
Коли уж говорим о соответствии RFC, то делать всё а не то что проще/понравилось.

 

Во фряхе до сих пор не проверяется длина хваддр
Удивительно... Но я всё равно не люблю FreeBSD :)

 

Не уверен что все пользователи будут грамотными.
1. Не грамотный пользователь в таком софте всё равно обязательно что-нибудь сломает.

2. Функция to_cidr используется только в 2х местах и данные которые она обрабатывает предоставляются libpcap. Уж если там будут маски с "дырками", то можно сразу убиваться.

 

Про проверку что пакет предназначен именно этому дхцп серверу по полю дхцп_сервер_ид я понял только когда запустил второй %)
Ну вообще в todo написано про то что надо делать QueryRej если клиент выбрал другой север, и ориентироваться всегда предполагалось именно на это.

 

 

Всем всем: выяснил, бага описанная выше (выявляющаяся при подсчёте udp checsum) не связана с последними правками, в предыдущей версии тоже было. Так что хуже чем в прошлой версии быть не должно. Ну а багу - конечно буду выковыривать...

 

[-Alt-], для начала проверьте новую версию, может это было из-за баги в работе кэша (хотя если кэш по прежнему не используется то нет смысла). Если не поможет то пожалуйста сделайте следующее:

1. Запустите с debug логом. Весь лог проблемной транзакции мне на мыло.

2. Сделайте пожалуйста бинарный дамп проблемной DHCP транзакции через tcpdump -s0 -w dump-file <filter>. Фильтр должен быть такой что бы было видно и запросы и ответы, лучше пусть будет что-то лишнее, сам если что потом отфильтрую. Полученный dump-file тоже мне на мыло.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Очень ОС зависимо, придётся под каждую ОС свой код писать, при чём не самый тривиальный. Оставлено на далёкое и счастливое коммунистическое будущее.
Если очень хочется, есть какая то очень кроссплатформенная либа которая использует под каждую ОС наилучший механизм:

под фряху kqueue

под винду IOCompletionPort и тп

 

 

Не очень понимаю как это может помочь.
Сузить область поиска в коде.

 

 

Такой кэш будет работать только для первого DHCPREQUEST от данного клиента.
Часто больше и не нужно, если листайм большой.

Это автоматом гарантирует актуальность кеша, и снизит нагрузку на базу: 1 запрос в базу на всё время жизни лизы.

 

 

Коли уж говорим о соответствии RFC
При некоторых конфигурациях сети это может работать не правильно или не иметь смысла, если пакеты не ходят в те сети откуда релей агенты доставляют запросы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если очень хочется, есть какая то очень кроссплатформенная либа которая использует под каждую ОС наилучший механизм:

под фряху kqueue

под винду IOCompletionPort и тп

Сейчас не хочется.

 

Сузить область поиска в коде.
Не думаю что это реально сузит область поиска.

 

Это автоматом гарантирует актуальность кеша, и снизит нагрузку на базу: 1 запрос в базу на всё время жизни лизы.
Это какой-то недокэш ИМХО :)

 

При некоторых конфигурациях сети это может работать не правильно или не иметь смысла, если пакеты не ходят в те сети откуда релей агенты доставляют запросы.
Но хуже от этого не станет. В самом плохом случае - мы просто не получим ICMP echo response от уже существующего адреса и тогда клиент нам пришлёт DHCPDECLINE. В лучшем - сразу разберёмся что там что-то не так, может даже предложим другой адрес.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кстати заметил замечательную вещь, во всех ответах db2dhcp

10.254.0.1.67 > 10.254.0.110.67: [udp sum ok]

А во всех isc

10.254.0.1.67 > 10.254.0.110.67: [bad udp cksum e27a!]

Т.е. то ли его не считает то ли не правильно считает, то ли это как-то связано с аппаратным checksum offloading на сетевых...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

2011-03-17 13:38:17 [10975:1090562752] Got DHCPDISCOVER (1) message from client 20:CF:30:CE:03:41 on vlan500/10.254.0.1 (relay 10.254.0.26)
2011-03-17 13:38:17 [10975:1090562752] DEBUG: Adding DHCP message to empty queue 'DHCP requests'
2011-03-17 13:38:17 [10975:1090562752] DEBUG: Queue (DHCP requests) length now is: 1, new requests: 1
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Trying to get DHCP request from queue 'DHCP requests'.
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Parsing DHCP message and preparing SQL statement.
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Found DHCP header variable: CLI-ETHER-ADDR = "20CF30CE0341"
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Can't extract value for variable "CLI-IP-ADDR" (code 50).
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Found DHCP options variable: CLI-IP-ADDR = ""
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Found DHCP options variable: OPT82-REMOTE-ID = "001E58A0DD68"
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Found DHCP options variable: OPT82-PORT = "15"
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Prevous SQL statement: "call get_dhcp_params("1CBDB986108C","2E2C11E2","001E58A828C9","11")"
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Executing SQL statement "call get_dhcp_params("20CF30CE0341","","001E58A0DD68","15")"
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Fetched 9 rows, 3 fields from DB.
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Option 'DHCP server ID' is not set. Set server ID = 10.254.0.1 (interface IP address).
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Adding DHCP message to empty queue 'Offers queue for device vlan500'
2011-03-17 13:38:17 [10975:1090871744] DEBUG: Queue (Offers queue for device vlan500) length now is: 1, new requests: 1
2011-03-17 13:38:17 [10975:1090871744] DEBUG: DHCP request removed from queue 'DHCP requests'. Queue len now is: 0, new requests: 0
2011-03-17 13:38:17 [10975:1090562752] Got DHCPINFORM (8) message from client E0:CB:4E:46:2D:EF on vlan500/10.254.0.1 (relay 10.254.0.88)
2011-03-17 13:38:17 [10975:1090562752] DEBUG: Adding DHCP message to empty queue 'DHCP requests'
2011-03-17 13:38:17 [10975:1090562752] DEBUG: Queue (DHCP requests) length now is: 1, new requests: 1
2011-03-17 13:38:17 [10975:1090563648] DEBUG: Trying to get DHCP request from queue 'DHCP requests'.
2011-03-17 13:38:17 [10975:1090563648] Ignore this message.
2011-03-17 13:38:17 [10975:1090563648] DEBUG: DHCP request removed from queue 'DHCP requests'. Queue len now is: 0, new requests: 0
2011-03-17 13:38:18 [10975:1090562752] Sending DHCPOFFER (2) to 20:CF:30:CE:03:41/62.140.228.211 via 10.254.0.1 (relay 10.254.0.26)
2011-03-17 13:38:18 [10975:1090562752] DEBUG: DHCP request removed from queue 'Offers queue for device vlan500'. Queue len now is: 0, new requests: 0
2011-03-17 13:38:18 [10975:1090562752] Got DHCPREQUEST (3) message from client 20:CF:30:CE:03:41 on vlan500/10.254.0.1 (relay 10.254.0.26)
2011-03-17 13:38:18 [10975:1090562752] DEBUG: Adding DHCP message to empty queue 'DHCP requests'
2011-03-17 13:38:18 [10975:1090562752] DEBUG: Queue (DHCP requests) length now is: 1, new requests: 1
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Trying to get DHCP request from queue 'DHCP requests'.
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Parsing DHCP message and preparing SQL statement.
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Found DHCP header variable: CLI-ETHER-ADDR = "20CF30CE0341"
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Found DHCP options variable: CLI-IP-ADDR = "3E8CE4D3"
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Found DHCP options variable: OPT82-REMOTE-ID = "001E58A0DD68"
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Found DHCP options variable: OPT82-PORT = "15"
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Prevous SQL statement: "call get_dhcp_params("20CF30CE0341","3E8CE4D3","001E58A0DD68","15")"
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Executing SQL statement "call get_dhcp_params("20CF30CE0341","3E8CE4D3","001E58A0DD68","15")"
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Fetched 9 rows, 3 fields from DB.
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Option 'DHCP server ID' is not set. Set server ID = 10.254.0.1 (interface IP address).
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Adding DHCP message to empty queue 'Ack queue for device vlan500'
2011-03-17 13:38:18 [10975:1090871744] DEBUG: Queue (Ack queue for device vlan500) length now is: 1, new requests: 1
2011-03-17 13:38:18 [10975:1090871744] DEBUG: DHCP request removed from queue 'DHCP requests'. Queue len now is: 0, new requests: 0
2011-03-17 13:38:18 [10975:1090562752] DEBUG: Trying to get DHCP request from queue 'Ack queue for device vlan500'.
2011-03-17 13:38:18 [10975:1090562752] Sending DHCPNAK (6) to 20:CF:30:CE:03:41/0.0.0.0 via 10.254.0.1 (relay 10.254.0.26)
2011-03-17 13:38:18 [10975:1090562752] DEBUG: DHCP request removed from queue 'Ack queue for device vlan500'. Queue len now is: 0, new requests: 0

 

mysql> call get_dhcp_params("20CF30CE0341","3E8CE4D3","001E58A0DD68","15");
+------+------+----------------------------------------+
| code | type | value                                  |
+------+------+----------------------------------------+
| 1009 |    5 | 62.140.228.211                         |
|    1 |    5 | 255.255.255.128                        |
|    3 |    5 | 62.140.228.129                         |
|    6 |    5 | 192.168.10.1,192.168.10.2,62.140.229.3 |
|   51 |    2 | 14400                                  |
|   42 |    5 | 192.168.10.1,192.168.10.2              |
|   58 |    2 | 7200                                   |
|   59 |    2 | 13800                                  |
|   66 |    4 | 10.254.0.1                             |
+------+------+----------------------------------------+
9 rows in set (0.00 sec)

Query OK, 0 rows affected, 1 warning (0.00 sec)

 

Т.е. похоже не в запросе дело, а что-то с внутренней логикой сервера....

Изменено пользователем [-Alt-]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В лучшем - сразу разберёмся что там что-то не так, может даже предложим другой адрес.
В случае чего деклайн придёт, а пинг это доп задержка.

У dnsmasq пинговалка отключается в конфиге.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В случае чего деклайн придёт, а пинг это доп задержка.
Есть RFC и этого достаточно, что бы не плодить своих "стандартов" и оставлять потомкам счастье разгребать нашу самодеятельность. Задержка конечно будет. И она предусмотрена в RFC и соответственно в клиентах.

 

[-Alt-], спасибо. Да, похоже что бага в логике сервера. Буду смотреть сегодня/завтра. Дампы трафика всё равно не помешают.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.