NiTr0 Posted June 20, 2015 Posted June 20, 2015 Если использовать пул, то получается нельзя скрипт запускать несколькими процессами, т.к есть маленькая вероятность выдачи 1-го и того же адреса двум абонентам разными процесами. lock-и юзать... хотя у меня - он многопоточный (перепиливал немного), можете зять за основу, выкладывал раньше, но - только настатику заточен... Вставить ник Quote
Ivan_83 Posted June 20, 2015 Author Posted June 20, 2015 Кто-то реально мерял у себя скорость работы с mysql? А смысл? У всех разные запросы по сложности, разные сервера по скорости. Вставить ник Quote
martini Posted June 21, 2015 Posted June 21, 2015 коннект к базе ни разу не падал. Вставить ник Quote
Cramac Posted August 11, 2015 Posted August 11, 2015 а никто не доделывал пул адресов? Что то мой метод не очень корректно работает. Вставить ник Quote
Cramac Posted August 15, 2015 Posted August 15, 2015 я все пул мучаю, как у меня работает не очень мне нравится. Сейчас хочу вставить условие на проверку. Мучал вчера то что мы добавляли новую db_get_offer_data но потом подумал может проще вставить условие в handle_discover. Сейчас оно выглядит у меня так: sub handle_discover {#my $dbh = $_[0];#my $fromaddr = $_[1];#my $dhcpreq = $_[2];my ($dhcpresp);$dhcpresp = GenDHCPRespPkt($_[2]);$dhcpresp->{options}->{DHO_DHCP_MESSAGE_TYPE()} = pack('C', DHCPOFFER);if (db_get_offer_data($_[0], $_[2], $dhcpresp) == 1) { send_reply($_[1], $_[2], $dhcpresp, $_[0]); #db_lease_offered($_[0], $_[2]);}else{# if AUTO_CONFIGURE (116) supported - send disable generate link local addrif (defined($_[2]->getOptionRaw(DHO_AUTO_CONFIGURE)) && $_[2]->getOptionValue(DHO_AUTO_CONFIGURE()) != 0) { $dhcpresp->addOptionValue(DHO_AUTO_CONFIGURE(), 0); send_reply($_[1], $_[2], $dhcpresp, $_[0]);}}} в версии БЕЗ пула так: sub handle_discover {#my $dbh = $_[0];#my $fromaddr = $_[1];#my $dhcpreq = $_[2];my ($dhcpresp);$dhcpresp = GenDHCPRespPkt($_[2]);$dhcpresp->{options}->{DHO_DHCP_MESSAGE_TYPE()} = pack('C', DHCPOFFER);if (db_get_requested_data($_[0], $_[2], $dhcpresp) == 1) { send_reply($_[1], $_[2], $dhcpresp, $_[0]); db_lease_offered($_[0], $_[2]);}else{# if AUTO_CONFIGURE (116) supported - send disable generate link local addrif (defined($_[2]->getOptionRaw(DHO_AUTO_CONFIGURE)) && $_[2]->getOptionValue(DHO_AUTO_CONFIGURE()) != 0) { $dhcpresp->addOptionValue(DHO_AUTO_CONFIGURE(), 0); send_reply($_[1], $_[2], $dhcpresp, $_[0]);}}} хочу добавить запрос к базе который возвращает либо число строк (колличество ИП на порту) или массив строк этих адресов (ИД строк) Нужно вставить запрос, потом условие что то типо: $sth = $_[0]->prepare("SELECT `cl_id` ... "); // возвратит массив строк //или такой запрос$sth = $_[0]->prepare("SELECT count(`cl_id`) ..."); // вернет 1 значение count(`cl_id`)смотря с чем проще оперироватьif (полученное >1){тут код если пул на выбранном портуif (db_get_offer_data($_[0], $_[2], $dhcpresp) == 1) { send_reply($_[1], $_[2], $dhcpresp, $_[0]); #db_lease_offered($_[0], $_[2]);}else{# if AUTO_CONFIGURE (116) supported - send disable generate link local addrif (defined($_[2]->getOptionRaw(DHO_AUTO_CONFIGURE)) && $_[2]->getOptionValue(DHO_AUTO_CONFIGURE()) != 0) { $dhcpresp->addOptionValue(DHO_AUTO_CONFIGURE(), 0); send_reply($_[1], $_[2], $dhcpresp, $_[0]);}}}else{тут код если 1 ип на портуif (db_get_requested_data($_[0], $_[2], $dhcpresp) == 1) { send_reply($_[1], $_[2], $dhcpresp, $_[0]); db_lease_offered($_[0], $_[2]);}else{# if AUTO_CONFIGURE (116) supported - send disable generate link local addrif (defined($_[2]->getOptionRaw(DHO_AUTO_CONFIGURE)) && $_[2]->getOptionValue(DHO_AUTO_CONFIGURE()) != 0) { $dhcpresp->addOptionValue(DHO_AUTO_CONFIGURE(), 0); send_reply($_[1], $_[2], $dhcpresp, $_[0]);}}} единственное для запроса нужны $dhcp_opt82_port_id $dhcp_opt82_chasis_id' $dhcp_opt82_vlan_id которые возвращает, как я понимаю my ($dhcp_opt82_vlan_id, $dhcp_opt82_unit_id, $dhcp_opt82_port_id, $dhcp_opt82_chasis_id); if (GetRelayAgentOptions($_[1], $dhcp_opt82_vlan_id, $dhcp_opt82_unit_id, $dhcp_opt82_port_id, $dhcp_opt82_chasis_id)) Вставить ник Quote
Cramac Posted August 15, 2015 Posted August 15, 2015 Должно получится что то типо: sub handle_discover { #my $dbh = $_[0]; #my $fromaddr = $_[1]; #my $dhcpreq = $_[2]; my ($dhcpresp); my ($dhcp_opt82_vlan_id, $dhcp_opt82_unit_id, $dhcp_opt82_port_id, $dhcp_opt82_chasis_id); $dhcpresp = GenDHCPRespPkt($_[2]); $dhcpresp->{options}->{DHO_DHCP_MESSAGE_TYPE()} = pack('C', DHCPOFFER); if (GetRelayAgentOptions($_[1], $dhcp_opt82_vlan_id, $dhcp_opt82_unit_id, $dhcp_opt82_port_id, $dhcp_opt82_chasis_id)) { $sth = $dbh->prepare("SELECT `cl_id` ... where ...=$dhcp_opt82_port_id ...=$dhcp_opt82_chasis_id' ..=$dhcp_opt82_vlan_id"); //вернет массив cl_id $sth->execute();if ($sth->rows()>1) //Если на порту больше 1 ИП{ if (db_get_offer_data($_[0], $_[2], $dhcpresp) == 1) { send_reply($_[1], $_[2], $dhcpresp, $_[0]); #db_lease_offered($_[0], $_[2]); }else{# if AUTO_CONFIGURE (116) supported - send disable generate link local addr if (defined($_[2]->getOptionRaw(DHO_AUTO_CONFIGURE)) && $_[2]->getOptionValue(DHO_AUTO_CONFIGURE()) != 0) { $dhcpresp->addOptionValue(DHO_AUTO_CONFIGURE(), 0); send_reply($_[1], $_[2], $dhcpresp, $_[0]); }}}else { if (db_get_requested_data($_[0], $_[2], $dhcpresp) == 1) { send_reply($_[1], $_[2], $dhcpresp, $_[0]); db_lease_offered($_[0], $_[2]); }else{# if AUTO_CONFIGURE (116) supported - send disable generate link local addr if (defined($_[2]->getOptionRaw(DHO_AUTO_CONFIGURE)) && $_[2]->getOptionValue(DHO_AUTO_CONFIGURE()) != 0) { $dhcpresp->addOptionValue(DHO_AUTO_CONFIGURE(), 0); send_reply($_[1], $_[2], $dhcpresp, $_[0]); }}} } //if (GetRelayAgentOptions} Поправьте меня Вставить ник Quote
lamka Posted August 16, 2015 Posted August 16, 2015 Cramac, а какая у вас задача? Т.е. что имеете ввиду под работой с пулом адресов? Адреса должны выдваться из пула свободных адресов? Так эта задача решается скорее запросами к БД, а не ковырянием скрипта. Вот чего я ни у кого не увидел, так это кэширования лиз в самом перле. Вставить ник Quote
Cramac Posted August 16, 2015 Posted August 16, 2015 Задача простая, сейчас выдаем адреса по опции, в некоторых местах поставили вифи, хочу чтоб он же выдавал клиентам вифи из пула адресов. Сейчас у меня так работает но не очень корректно. Вот и хочу поправить. Вставить ник Quote
lamka Posted August 24, 2015 Posted August 24, 2015 Потихоньку разбираюсь в коде. Не знаю баг или фича, но вот: в send_reply() if ($_[1]->flags() == 0 || 1) {# send unicast XXXXXXXXX - flags ignored! Вставить ник Quote
Ivan_83 Posted August 24, 2015 Author Posted August 24, 2015 Потому что оно отправляет релей агенту, а броадкаст там не реализован, насколько помню. Вставить ник Quote
lamka Posted August 25, 2015 Posted August 25, 2015 выражение в скобках всегда истинно - я про это Вставить ник Quote
martini Posted August 25, 2015 Posted August 25, 2015 конечно всегда истинно, Иван ведь сказал что бродкаст не реализован, вот и шлем все юникастом в любом случае.. А условие сделано на всяк случай, вдруг ктото прикрутит работу без релея ) Вставить ник Quote
lamka Posted September 11, 2015 Posted September 11, 2015 (edited) Работа без релея прикрутилась одной строкой в send_reply(): setsockopt($SOCKET_RCV, SOL_SOCKET, SO_BROADCAST, $toaddr eq $ADDR_BCAST ? 1 : 0); Всовывать перед отправкой пакета: send($SOCKET_RCV, $dhcpresppkt, 0, $toaddr) || logger(0, "send error: $!"); Вроде все четко работает, но только с одним потоком. Если делать несколько, то каждый поток зависать секунд на 10 перед ответом на запрос. Даже не знаю куда смотреть. Может потому что под виндой (dwimperl) тестирую? И еще вопрос: зачем к ответам сервера прикручивать 82 опцию? Без них свитч или релей не поймет куда релеить? Я это убрал, никаких побочных эфектов не заметил. Edited September 11, 2015 by lamka Вставить ник Quote
martini Posted September 11, 2015 Posted September 11, 2015 если в запросе есть опт82 - то и в ответе она должна быть Вставить ник Quote
lamka Posted September 11, 2015 Posted September 11, 2015 Да, почитал уже RFC 3046 DHCP servers claiming to support the Relay Agent Information option SHALL echo the entire contents of the Relay Agent Information option in all replies. If a server is unable to copy a full Relay Agent Information field into a response, it SHALL send the response without the Relay Information Field, and SHOULD increment an error counter for the situation. Хотя, видимо, это не так уж и страшно. Вставить ник Quote
NiTr0 Posted September 11, 2015 Posted September 11, 2015 Хотя, видимо, это не так уж и страшно. То, что не по RFC - рулетка: на одном вендоре заработает, на другом - встанет раком... Вставить ник Quote
Ivan_83 Posted September 11, 2015 Author Posted September 11, 2015 Работа без релея прикрутилась одной строкой в send_reply(): Там было следующее. 1. Приём без релей агента вроде не работал в ряде случаев 2. Если клиент не выставил броадкаст флаг то ему нужно отправлять ответ юникастом на его мак адрес, а для этого нужно весь пакет ручками собирать, включая юдп заголовок Выставлять/снимать флаг с сокета - НЕ ПРАВИЛЬНО. С этим сокетом работает много потоков одновременно, и пока может возникнуть ситуация когда один поток выставил флаг, другой его тут же снял, а первый поток только поставил на отправку, в итоге каша вместо результата. Правильным решением будет создание ещё одного сокета для отправки броадкастов. И ещё один для отправки юникастом "сырых" пакетов собранных руками. Вставить ник Quote
lamka Posted September 11, 2015 Posted September 11, 2015 то ему нужно отправлять ответ юникастом на его мак адрес, а для этого нужно весь пакет ручками собирать, включая юдп заголовок Не понял как можно послать ip пакет на мак адрес? Если у клиента нет ciaddr в запросе, то только бродкаст. Иначе как без ip слать? Мне кажется, что если у клиента нет ciaddr и флага бродкаста, то пошел он нафиг. Вообще такое часто встречается? Правильным решением будет создание ещё одного сокета для отправки броадкастов. И ещё один для отправки юникастом "сырых" пакетов собранных руками. А клиенты не проверяют исходящий порт сервера? Ведь придется сокеты вешать на разные исходящие порты, не только 68? Вставить ник Quote
Ivan_83 Posted September 11, 2015 Author Posted September 11, 2015 Не понял как можно послать ip пакет на мак адрес? Если у клиента нет ciaddr в запросе, то только бродкаст. Иначе как без ip слать? Мне кажется, что если у клиента нет ciaddr и флага бродкаста, то пошел он нафиг. Вообще такое часто встречается? Да легко. Заполняем L2 заголовок правильно и пакет уходит кому надо. Вон PPPoE шлёт же на мак клиента, без всяких IP адресов, чем я хуже?) Мак клиента есть в запросе. Броадкаст флаг - вроде как костыль, который позже появился. А клиенты не проверяют исходящий порт сервера? Ведь придется сокеты вешать на разные исходящие порты, не только 68? Нужно уточнять документацию. Есть ещё REUSEPORT флаг на сокет, но тогда пакеты будут дублироватся и их нужно будет или вычитывать из сокета или забить на это и после заполнения буфера они сами начнут дропатся. Вставить ник Quote
lamka Posted September 11, 2015 Posted September 11, 2015 Заполняем L2 заголовок правильно и пакет уходит кому надо. Вон PPPoE шлёт же на мак клиента, без всяких IP адресов, чем я хуже?) Мак клиента есть в запросе. Видимо я чего-то не понимаю. PPPoE - не относится к IP-протоколам, он сам по себе. И в заголовке IP-пакета нет данных о мак-адресе. Клепать ethernet фреймы - как-то уж слишком экстремально. Есть ещё REUSEPORT флаг на сокет, но тогда пакеты будут дублироватся и их нужно будет или вычитывать из сокета или забить на это и после заполнения буфера они сами начнут дропатся. Пожалуй, логично было бы вынести работу с сокетом из потоков в основной и сделать очередь (благо что udp - пакеты улетают мгновенно), . Т.е. в потоках читаются запросы, идет обращение к БД и т.п., а ответы суются в очередь, которую обслуживает отдельный поток. Вставить ник Quote
Ivan_83 Posted September 12, 2015 Author Posted September 12, 2015 Видимо я чего-то не понимаю. PPPoE - не относится к IP-протоколам, он сам по себе. Это я к тому, что отправить на мак можно любой пакет и IP тут никаким боком. И в заголовке IP-пакета нет данных о мак-адресе. Мак адрес у дхцп сервера есть из запроса, клиент сам присылает свой мак. Можно было бы и в л2 пакета смотреть, но это не нужно, разве что для секурности, чтобы подавлять работу подавителей дхцп серверов. :) Клепать ethernet фреймы - как-то уж слишком экстремально. Там сложного ничего нет. Совсем ничего. Единственная замута это вланы и дополнение конфига. IP/UDP сложнее - для них нужно суммы считать. Пожалуй, логично было бы вынести работу с сокетом из потоков в основной и сделать очередь (благо что udp - пакеты улетают мгновенно), . Т.е. в потоках читаются запросы, идет обращение к БД и т.п., а ответы суются в очередь, которую обслуживает отдельный поток. Нет. Чтобы был полноценный сервер без релея нужно принимать и отправлять прямо с интерфейса через BPF прослойку. Те не городить дрочиво броадкаст опции сокета, а собирать л2+л3+л4+дхцп пакет самому и слать в сеть. Тогда и очереди никакие не нужны. Я заглядывал в dnsmasq там вроде именно так и сделано было, помню видел программы-фильтры дхцп запросов для BPF. (а может это dhcpdump был) Вставить ник Quote
martini Posted September 13, 2015 Posted September 13, 2015 Иван - все правильно говоришь, все работает. Написал от нечего делать более развернутый ДХЦП, дергает пакеты из ядра, разбирает все сам , проверяет в базе и отдает назад собирая полный эзернет заголовок и отправляет на мак юзера и юникаст и броадкаст. Причем добавил даже unnumbered туда , осталось шейпер прикрутить и вебку хоть какую то сделать... Ну и получится какой то аналог то ли циски, то ли акселя )) Вставить ник Quote
pppoetest Posted September 13, 2015 Posted September 13, 2015 Аксель, емнип, модуль ядерный, а это чистой воды юзерленд. Вставить ник Quote
martini Posted September 13, 2015 Posted September 13, 2015 а причем тут это ? я в юзерленде только дхцп пакеты разгребаю и собираю, всей маршрутизацией занимается ядро как и раньше.. Вставить ник Quote
NiTr0 Posted September 13, 2015 Posted September 13, 2015 Аксель, емнип, модуль ядерный, а это чистой воды юзерленд. там тот модуль нужен только для псевдоинтерфейсов... Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.