Jump to content

Recommended Posts

Posted

Если использовать пул, то получается нельзя скрипт запускать несколькими процессами, т.к есть маленькая вероятность выдачи 1-го и того же адреса двум абонентам разными процесами.

lock-и юзать... хотя у меня - он многопоточный (перепиливал немного), можете зять за основу, выкладывал раньше, но - только настатику заточен...

  • Replies 364
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

Posted
Кто-то реально мерял у себя скорость работы с mysql?

А смысл?

У всех разные запросы по сложности, разные сервера по скорости.

  • 1 month later...
Posted

я все пул мучаю, как у меня работает не очень мне нравится.

Сейчас хочу вставить условие на проверку. Мучал вчера то что мы добавляли новую 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))

Posted

Должно получится что то типо:

 

 

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}

 

 

Поправьте меня

Posted

Cramac, а какая у вас задача? Т.е. что имеете ввиду под работой с пулом адресов? Адреса должны выдваться из пула свободных адресов? Так эта задача решается скорее запросами к БД, а не ковырянием скрипта. Вот чего я ни у кого не увидел, так это кэширования лиз в самом перле.

Posted

Задача простая, сейчас выдаем адреса по опции, в некоторых местах поставили вифи, хочу чтоб он же выдавал клиентам вифи из пула адресов. Сейчас у меня так работает но не очень корректно. Вот и хочу поправить.

  • 2 weeks later...
Posted

конечно всегда истинно, Иван ведь сказал что бродкаст не реализован, вот и шлем все юникастом в любом случае.. А условие сделано на всяк случай, вдруг ктото прикрутит работу без релея )

  • 3 weeks later...
Posted (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 by lamka
Posted

Да, почитал уже 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.

Хотя, видимо, это не так уж и страшно.

Posted
Работа без релея прикрутилась одной строкой в send_reply():

Там было следующее.

1. Приём без релей агента вроде не работал в ряде случаев

2. Если клиент не выставил броадкаст флаг то ему нужно отправлять ответ юникастом на его мак адрес, а для этого нужно весь пакет ручками собирать, включая юдп заголовок

 

Выставлять/снимать флаг с сокета - НЕ ПРАВИЛЬНО.

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

Правильным решением будет создание ещё одного сокета для отправки броадкастов.

И ещё один для отправки юникастом "сырых" пакетов собранных руками.

Posted

то ему нужно отправлять ответ юникастом на его мак адрес, а для этого нужно весь пакет ручками собирать, включая юдп заголовок

Не понял как можно послать ip пакет на мак адрес? Если у клиента нет ciaddr в запросе, то только бродкаст. Иначе как без ip слать? Мне кажется, что если у клиента нет ciaddr и флага бродкаста, то пошел он нафиг. Вообще такое часто встречается?

 

Правильным решением будет создание ещё одного сокета для отправки броадкастов.

И ещё один для отправки юникастом "сырых" пакетов собранных руками.

А клиенты не проверяют исходящий порт сервера? Ведь придется сокеты вешать на разные исходящие порты, не только 68?

Posted
Не понял как можно послать ip пакет на мак адрес? Если у клиента нет ciaddr в запросе, то только бродкаст. Иначе как без ip слать? Мне кажется, что если у клиента нет ciaddr и флага бродкаста, то пошел он нафиг. Вообще такое часто встречается?

Да легко.

Заполняем L2 заголовок правильно и пакет уходит кому надо.

Вон PPPoE шлёт же на мак клиента, без всяких IP адресов, чем я хуже?)

Мак клиента есть в запросе.

Броадкаст флаг - вроде как костыль, который позже появился.

 

А клиенты не проверяют исходящий порт сервера? Ведь придется сокеты вешать на разные исходящие порты, не только 68?

Нужно уточнять документацию.

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

Posted

Заполняем L2 заголовок правильно и пакет уходит кому надо.

Вон PPPoE шлёт же на мак клиента, без всяких IP адресов, чем я хуже?)

Мак клиента есть в запросе.

Видимо я чего-то не понимаю. PPPoE - не относится к IP-протоколам, он сам по себе. И в заголовке IP-пакета нет данных о мак-адресе. Клепать ethernet фреймы - как-то уж слишком экстремально.

 

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

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

Posted
Видимо я чего-то не понимаю. PPPoE - не относится к IP-протоколам, он сам по себе.

Это я к тому, что отправить на мак можно любой пакет и IP тут никаким боком.

 

И в заголовке IP-пакета нет данных о мак-адресе.

Мак адрес у дхцп сервера есть из запроса, клиент сам присылает свой мак.

Можно было бы и в л2 пакета смотреть, но это не нужно, разве что для секурности, чтобы подавлять работу подавителей дхцп серверов. :)

 

Клепать ethernet фреймы - как-то уж слишком экстремально.

Там сложного ничего нет. Совсем ничего.

Единственная замута это вланы и дополнение конфига.

IP/UDP сложнее - для них нужно суммы считать.

 

 

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

Нет.

Чтобы был полноценный сервер без релея нужно принимать и отправлять прямо с интерфейса через BPF прослойку.

Те не городить дрочиво броадкаст опции сокета, а собирать л2+л3+л4+дхцп пакет самому и слать в сеть. Тогда и очереди никакие не нужны.

Я заглядывал в dnsmasq там вроде именно так и сделано было, помню видел программы-фильтры дхцп запросов для BPF. (а может это dhcpdump был)

Posted

Иван - все правильно говоришь, все работает. Написал от нечего делать более развернутый ДХЦП, дергает пакеты из ядра, разбирает все сам , проверяет в базе и отдает назад собирая полный эзернет заголовок и отправляет на мак юзера и юникаст и броадкаст. Причем добавил даже unnumbered туда , осталось шейпер прикрутить и вебку хоть какую то сделать... Ну и получится какой то аналог то ли циски, то ли акселя ))

Posted

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

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...