Назначение сетевого адреса Ethernet-устройству.
8757
35
Итак, есть у меня некое Ethernet-устройство, собирающее данные и общающееся по сети с компом по TCP/IP. Есть поддержка UDP. Никакого другого интерфейса, кроме Ethernet-а у устройства нет. Вопрос: как при подключении в локальную сеть назначать ему IP-адрес?
Немного расшифрую. Я занимаюсь программированием этого устройства. Моих базовых знаний по TCP/IP хватает чтобы открыть сокет, назначить ему статический IP, и подцепиться с другой стороны по нему. А вот как выполняется поиск устройств в сетях, я не знаю. И в литературе пока ещё не нашёл. Так что это... please help:улыб:
AnotherBoris
IP адреса в сети раздают DHCP сервера.
Устройство (не важно Ethernet или другая физически сеть используется) посылает широковещательный запрос "DHCP сервер, отзовись!", после чего DHCP сервер (если отзовется) выдает параметры IP соединения для этого устройства.
KSergey
Цитирую datasheet:
Support Hardwired TCP/IP Protocols : TCP, UDP, ICMP, IPv4 ARP, IGMP, PPPoE, Ethernet

Я правильно понимаю, что для посылки такого рода запросов используется ICMP? Но, предположим, она получила адрес, выставила его у себя, но как другая-то машина в сети найдёт железку? Я вижу следующий вариант:
- Железка запрашивает адрес и маску подсети, получает их.
- Железка октрывает UDP-сокет и начинает слушать.
- Используя broadcast UDP пакеты ищем железку в сети.
- Работаем с железкой.
Так-то всё вроде бы ок, вот только мне крайне не хочется открывать лишние сокеты. Это сразу отжирает мне половину и без того некрупного буфера контроллера. А включение-выключение сокетов усложнит архитектуру и ухудшит надёжность системы.

Но бог с ним,это уже мои проблемы, но вот скажите мне, что делать, если локальная сеть не имеет DHCP сервера? Если это старая добрая сеть на пяток машин со статическими IP. Как в этом случае решать проблему? (вариант "включить DHCP сервер" не канает :))
AnotherBoris
обычно фирмы производители делают для своих
mcu усеченные стеки протоколов.
Для начала на сайте производителя поищите библиотеки стеков.
описание библиотек, апноты с примерами ну и для общего развития документацию
по протоколам (rfc) в инете есть переведеная на русский
AnotherBoris
а мануала к этому некоему устройству нет, где бы написано было, как его в сеть-то подключать? Можбыть, у него, как это часто принято с промышленными устройствами, настройки проливаются через утилиту конфигурации с компьютера?
PN
"Некое устройство", увы, разрабатывает группа товарищей, к которой принадлежит ваш покорный слуга:улыб:Как следствие - мануала ещё нет:улыб:С другой стороны, на контроллер w5100, используемый в "устройстве" мануалов дофига, вот, например: http://www.efo.ru/cgi-bin/go?2595. Там даже есть реализация DHCP клиента. Но, спасибо, KSergey я теперь знаю верное направление в одном из случаев. А что делать во втором? Просто в силу моей специализации, я не очень-то себе представляю творящийся в сетях хаос, все эти стеки протоколов, чего куда и через что. Потому и спрашиваю, что в таком случае делают люди. Как, я разберусь, но что? Просто я навскидку не припоминаю ни одного периферийного сетевого устройства, цепляющегося напрямую к Ethernet и не имеющего других интерфейсов для обмена информацией. Соответственно, не знаю, как в таком случае поступают люди. Велосипед-то изобретать не хочется.
Так что, с учётом уже полученной информации, несколько переформулирую вопрос: как достучаться до сетевого устройства, в сети без DHCP, имеющего неизвестные сетевые настройки.
AnotherBoris
как найти то не знаю что, ничего не зная об этом? ))
если известен MAC адрес этого устройства, то можно чисто теоретически узнать его IP адрес по MAC-у, при условии что оба устройства подключены к одному broadcast домену (читай воткнуты в один свич) - вот тут можно почитать "вводную".
ну а если только известно, что устройство существует, но ничего другого неизвестно - то видимо никак.
AnotherBoris
+ можно почитать про APIPA - по идее ваша железяка при отсутствии DHCP может сама выбрать себе адрес из этого диапазона при соблюдении всех нюансов RFC - ну а там в принципе уже другой вопрос стоит тогда - как узнать что за адрес она выбрала...
AnotherBoris
Просто я навскидку не припоминаю ни одного периферийного сетевого устройства, цепляющегося напрямую к Ethernet и не имеющего других интерфейсов для обмена информацией.
Таких железок вагон ималенькая тележка. Есть несколько способов:
1. Получаем адрес по DHCP и если нет сервера в сети, по таймауту используем APIPA.
2. Приколачиваем к железке статику из какогонибудь неособо популярного диаппазона (например 192.168.101.1) и пишем об этом в мануале, а еще лучше на стикере железки вместе с маком.
3. Железка изначально имеет только мак. Пишем утелю которая может находить девайс по маку и позваляет задавать настройки для IP стека. Протокол обмена тут вы можете сами придумать, стандартов нет.

Ну и естественно все эти 3 пункта можно комбинировать насвой вкус.
AnotherBoris
Просто я навскидку не припоминаю ни одного периферийного сетевого устройства, цепляющегося напрямую к Ethernet и не имеющего других интерфейсов для обмена информацией.
Принт-серверы, беспроводные точки доступа, разнообразные маршрутизаторы и коммутаторы - все они только езернетом цепляются и управляются или через встроенный веб-сервер, или внешней утилитой, которая их видит своим способом. Изначально у устройства могут быть (и, как правило, прошиты) некоторые сетевые атрибуты, которые принято даже писать на наклейке на корпусе. При конфигурировании компьютеру ставятся атрибуты из этой же подсети, устройтво настраивается и подключается в рабочую сеть. Но бывает и так, что сетевые настройки непрописаны, тогда только внешней утилитой конфигурируется - подключил в сеть, запустил утилу, пролил сетевые настройки, подключился по ним и работаешь.
Mad_Dollar
при условии что оба устройства подключены к одному broadcast домену (читай воткнуты в один свич)
Небольшая поправочка, свитчей может быть сколь угодно, броадкаст домен, какправило, ограничен роутером.
Mozepiy
ну свичи тоже разные бывают, разной степени "ума". поэтому лучше не загадывать, что это будет _гарантированно_ работать больше чем через один свич.
Mad_Dollar
Бывают вендоры разного ума, или криворукие админы, но это уже из другой оперы ,)
Свитч, каким бы он умным небыл, если ненаходит мак в своей таблице, пуляет пакет вовсе порты аки хаб и ждет с какого прелетит ответный, на основе этого он и строит свою мак таблицу, дальше трафик пойдет уже только по нужным портам. В противном случае, ниокаких DHCP серверах и речи бы быть немогло.
Mozepiy
3. Железка изначально имеет только мак. Пишем утелю которая может находить девайс по маку и позваляет задавать настройки для IP стека. Протокол обмена тут вы можете сами придумать, стандартов нет.
А можно подробнее? Что почитать про реализацию обмена по MAC-адресам из-под винды? Для меня это был бы идеальный вариант.

И да, мы и сами клеим шильдики на свои железки, и да, я понимаю, что таких железок вагон и маленькая тележка - просто я о них не знаю. Мне достаточно понимания, что они всё-таки есть, а, значит, люди подобные проблемы уже решали. Но всё равно - спасибо за ответы:улыб:
AnotherBoris
Покопать в сторону WinPCap наверное, я больше по линуксам. Нелишним будет ознакомится с RawSockets, но в винде с ними всю дорогу было более чем печально. Также могут помочь исходники какогонибудь WakeOnLan.
Mozepiy
мы сейчас с вами обсуждаем то, что оба понимаем и с чем согласны, но мой жизненный опыт показывает, что это пусть и редко, но случается ))
Mad_Dollar
Дык я к тому клоню, что это проблемы конечного пользователя, а не разработчика. В конце концов, железку всегда можно подрубить к компу напрямую и сконфигурять, правда как показывает богатый опыт и этого бывает недостаточно ,)
AnotherBoris
Если не секрет, чего за железка такая? Для чего она вобще? И нафига её кому-то/чему-то в сети видеть.
Почему нельзя ограничется статическим назначением IP-адреса? Сами понимаете, что постоянно сменяющийся IP-адрес порождает проблемы. Если в железке памяти мало, то нафига её занимать всякими DHCP-клиентами. Возможно этого и не нужно. Всё зависит от назначения данного девайса.
Вобще есть такой протокол, ARP называется. Протокол определения адреса если по русски. Вобщем если просматривать ARP-таблицу (сопоставление аппаратного адреса IP-адресу) на предмет определенных mac-адресов, то можно и IP-адрес найти.
AnotherBoris
На сколько я понимаю, где-то вот тут почитать про Ethernet.
Ну потому что раз вы в эту сеть воткнулись - то вам точно должен быть известен MAC-адрес устройства, и таким образом вы можете организовать с ним сетевой обмен.
Все прочее (типа IP) - это уже выше, над Ethernet протоколом.
Если Ethernet вы не организовали - тогда вообще не судьба. Но вы его явно организовали и MAC-адрес железки знаете. Ну либо надо слать какой-то широковещательный Ethernet пакет в сеть, который железка поймает, опознает и на него ответит (типа как обнаруживаются в сетях всякие принт-серверы родными ихними утилитами, например). Ну а когда удалось как-то установить с ней обмен (родной утилитой вашего производства, например) - ее уже можно конфигурировать.
Ну как вариант.

Прошить дефолтный IP-адрес - тоже вполне себе стандартная практика.
Считается, что если этот адрес не устраивает пользователя - он всегда может устройство подключить не в сеть, а к выделенному компьютеру, подключиться к устройству уже по IP-протоколу какой-то утилитой (или браузером, если в железке WEB-сервер реализован) по прошитому адресу и поменять адрес на нужный.
AnotherBoris
Итак, есть у меня некое Ethernet-устройство, собирающее данные и общающееся по сети с компом по TCP/IP. Есть поддержка UDP. Никакого другого интерфейса, кроме Ethernet-а у устройства нет. Вопрос: как при подключении в локальную сеть назначать ему IP-адрес?
Немного расшифрую. Я занимаюсь программированием этого устройства. Моих базовых знаний по TCP/IP хватает чтобы открыть сокет, назначить ему статический IP, и подцепиться с другой стороны по нему. А вот как выполняется поиск устройств в сетях, я не знаю. И в литературе пока ещё не нашёл. Так что это... please help:улыб:
Зачем Вам это? Вы заработаете на этом? Или это ваше "хобби"?
AnotherBoris
И... займёмся некропостингом:улыб:

Итак, некое Ethernet-устройство за это время обрело мясо, наростило софт, но... есть небольшая проблемка: пропадает часть TCP пакетов. При подключении в локальную сеть (хаб + свитч) теряется где-то 0.1% пакетов, а при подключениии напрямую - 0.01-0.03%. Симптомы следующие: железка пакет посылает. Физически, конечно, в линии я не смотрел, но счётчик посланных пакетов она уверенно инкрементирует. В то же время клиентская часть этот пакет не принимает. В сокете между предыдущим и следующим пакетом данных нет вообще. Из чего я делаю вывод, что TCP почему-то этот пакет режет.

Собственно, вопрос: господа знатоки, как по-вашему, такой процент потерь нормален или это где-то мой косяк?

Немного технической информации: пакеты я посылаю размером чуть менее (насколько позволяет неделимость данных) 1460 байт. Поток данных около 8 Mbit/s. В обратную сторону траффика нет.

Ну и... возникает вопрос как эту проблему решать.
Есть тупой вариант: дублировать все пакеты:улыб:Жестоко, но довольно хорошо увеличит надёжность приёма:улыб:Легко реализуемо.
Есть вариант чуть сложнее: хранить в железке последние n пакетов, а клиентом, если что, запрашивать перепосылки. Проблема в ограниченной памяти железки - я смогу хранить лишь 8 пакетов, что составляет где-то 15 мс. В принципе, для локальной сети достаточно, но возникни у клиента затык (а они периодически возникают спасибо антивирусам, браузерам и прочей клиентской фигне, которую пользователи ставят на якобы рабочую машину), и наш пакет тут же будет пропущен.
И есть ещё одна модификация предыдущего варианта: подтверждать все пакеты. Та же проблема с затыком, разве что чуть другая реакция. Не уверен пока в плюсах и минусах метода.

Опять же, ваши мысли по поводу.

Заранее благодарен.
AnotherBoris
для tcp в принципе ситуация resubmit не является какой-то ненормальной, потому как tcp суть протокол "гарантированной доставки", когда вне зависимости от процента потерь по пути (а на разных участках пути могут быть разные каналы связи с разным качеством и etc) данные либо доставляются в том порядке в котором они отправлены, либо не доставляются вообще.

грубо говоря, на уровне самого tcp ожидаемый процент потерь - 0%. Все что больше нуля - не правильно. на уровне сетевом (Ethernet) потери допустимы, на уровне tcp - из не может быть.

Теперь сама суть - каждое получение данных приемник подтверждает отправителю (http://ru.wikipedia.org/wiki/TCP).
то есть:
1) отправитель отсылает пакеты с номерами 1, 2, 3, 4, 5 (и в буфере отправки у него еще пакеты 6, 7, 8, 9)
таким образом, в буфере отправки пакеты имеют следующий статус:
1, 2, 3, 4, 5 - отправлен, не подтвержден
6, 7, 8, 9 - не отправлен
2) приемник получает пакеты с номерами 1, 2, 3, 5 - (потерялся пакет номер 4 - и это не важно где)
приемник отправляет назад сообщение "принял пакеты по номер 3 включительно"
3) передатчик получает сообщение "принято, максимальный номер принятого пакета - 3", удаляет из буфера пакеты 1-3, отправляет следующие 5 пакетов: 4, 5, 6, 7, 8
таким образом буфер на отправку выглядит как:
4, 5, 6, 7, 8 - переданы, нет подтверждения
9 - не передан

ну и дальше по этому же алгоритму пока все данные не будут переданы
что и как делает приемник с пакетом номер 5 при отсутствующем 4-ом вопрос конкретной реализации приемника, в рамках tcp должны быть повторно посланы все пакеты, получение которых не было подтверждено. ситуации, когда отправлено было 1, 2, 3 а пришло 1, 3, 2 - тоже реализуются на стороне приемника через организацию буфера приема, таймауты и разные алгоритмы, основная цель которых минимизировать resubmit пакетов если в пути пакеты перемешались и гарантировать приемлемую скорость получения данных с таймаутами "ожидания" при обработке "перемешанных пакетов" в последовательности приема.

что это означает:
1) возможно буфер отправки стоит увеличить - 8 пакетов это очень скромный буфер для на скорости отправки данных в восемь мегабит - это грубо буфер всего на ~ 12-15 миллисекунд. в качестве допинфы можешь почитать http://www.securitylab.ru/analytics/243414.php - тут для домохозяет и эникеев пытаются рассказать что есть буфер и каков его размер должен быть. ну и вариантов есть несколько:
А) - увеличивать буфер у себя - возможно самый правильный вариант, хотя нужно оценивать гемморность добавления лишней памяти под этот буфер в твою эмбедовку
Б) - тюнить tcp-стек на клиенте - результат не гарантирован, возможность для этого есть только тогда, когда и клиента на уровне железяки ты тоже разрабатываешь.
В) - обучить алгоритмы, которые обрабатывают посылаемый тобой data flow в 8 мегабит (на клиенте имеется ввиду) к возможному протериванию части пакетов, возможно здесь имеет смысл использовать udp вместо tcp - но тогда "выстраивание" "цепочки данных" из udp пакетов целиком и полностью переносится на клиента.
где практикуют такое - ну это классика - voip / потоковое вещание, там в случае "провала" на каком-то этапе декодер тупо ждет следующий "ключевой кадр" и реинициализирует обработку данных с этого ключевого кадра.

что именно проще сделать - ну смотреть нужно, а вообще буфер отправки в 12 Кb для потока в 8 MB/s маловат будет...
AnotherBoris
алсо, можешь почитать вот тут: http://technet.microsoft.com/ru-ru/magazine/2007.01.cableguy.aspx
то, что у тебя потери меньше процента на потоке данных в 8 мегабит и буффере на 12К - да это тебе просто везет (+лабораторные условия сказываются - в реальной жизни будет куда больше)
Mad_Dollar
Ага. Мило. Особенно учитывая, что я говорил о программном буфере:улыб:А аппаратный у меня аж 8192 байта:улыб:
Отсюда я делаю вывод, что 8mbit на TCP мне не светит при таком железе. Придётся переходить на UDP и гнать пакеты без отклика. Я же правильно понимаю, что UDP-пакеты будут уходить на максимальной скорости? Софт, кстати, у меня принимает пакеты в любом порядке, с этой стороны я проблем не вижу.
AnotherBoris
ну здесь вопрос у тебя возникнет не в том что они прийдут как попало, а в том, что и UDP пакеты тоже могут теряться - проблема у тебя может быть в этом.
если и это не проблема, то гони все в UDP и "сглаживай" возможные провалы / разный порядок доставки на стороне приемника софтом
AnotherBoris
Я думаю Вам полезно почитать вот эту статью http://habrahabr.ru/post/138081/
ну и в конце статьи по ссылкам.
Mad_Dollar
Да у меня софтина уже разгребает весь входной поток данных на независимые друг от друга датаграммы. Ей плевать на порядок и она отлично находит пропущенные пакеты. Так что на эту особенность UDP мне, слава богу, плевать. Главное, чтобы я мог со стороны железки поток как минимум в 8Mbit слать. И это... Бакс, спасибо за советы:улыб:Прямо выручаешь:улыб:
AnotherBoris
Итак, UDP:улыб:

Первое, с чем столкнулся - это изменение формата посылки пакетов.

Если верить WinAPI:

Sendto - посылает data куда-то (не могу процитировать точнее, пишу с чужой машины)
Recvfrom - принимает datagram откуда-то.

Меня смущает то, что принимаем мы датаграмму, а вот посылаем абстрактное data. Если бы мы и посылали датаграмму, я бы упаковал по одному своему пакету в каждую датаграмму и беды бы не знал, а как оно на самом деле? Могу ли я быть уверенным на 100%, что вызов sendto пошлёт мне именно одну датаграмму с указанными мною данными? Сразу оговорюсь, что пакеты туда у меня мелкие - 10-20 байт и уж точно не больше максимального размера TCP пакета. Так что резать датаграммы он вроде бы не должен. По логике, и склеивать не должен, ибо каждая датаграмма может идти разным адресам. То есть, рассуждая логически, вроде бы sendto тоже посылает именно датаграмму. Но сомнения остаются:улыб:
AnotherBoris
да, будь уверен это датаграмма, у тебя один пакет с данными какого размера? Если он в MTU пролазит целиком то вообще даже не парься на эту тему.
AnotherBoris
Wireshark вам в помощь.
Сразу будет видно чего посылаете и как посылаете.
Mad_Dollar
Ну... это измерительная система. Туда идёт поток команд, в основном (те самые мелкие пакеты по 10-20 байт), причём только в режиме настройки. В режиме же работы система гонит те самые 8 Mbit/s оттуда. В TCP варианте я гнал пакеты по 1460 байт максимум (насколько позволяла неделимость данных), в UDP, я так понимаю, размер датаграммы должен быть таким же? Впрочем, поменять это не сложно - размер пакета забит в коде константой.

И спасибо за Wireshark. Не уверен, что пригодится сейчас, а конце концов мне только формат пакета поменять да протокол чуть-чуть, но в конце коцов, не последний день живём!:улыб:
AnotherBoris
ну по идее размер здесь можно оценивать с двух сторон (если у тебя пакет данных 10-20 байт)
1) в каждый пакет UDP пакет складывать 1 пакет данных (те самые 10-20 байт). Плюсы - если пакет "протеряется" то "протеряется" только один пакет данных. Минусы - pps будет адский, сеть уложить можно влет, коммутаторы слягут по пути (а не в лабе - почти наверняка).
2) укладывать максимальное количество данных в UDP-пакет (как ты делал с TCP). Плюсы - пакеты будут теряться редко, но если вдруг все-таки какой-то UDP-пакет протеряется то протеряется 1400/15 ~ 90 пакетов твоих данных, которые железяка намеряла.

Я бы делал компромисс (полагая что MTU не 1460 как в Ethernet классическом, а скажем ~ 1200 на всякий случай - мало ли по пути какое будет MTU, может у клиента потом будет весьма специфическая сеть (или связь будет через какой-нибудь мтс-олень-модем, а там у опсосов с MTU могут разные чуйдеса твориться).

Как я понимаю добавлять буфер в железяку проблемно, чтобы на уровне протокола приложения можно было перезапросить какие-то данные, и когда будешь потом дебажить почему в лабе работает а у клиента нет про MTU не вспомнишь, а у клиента совершенно случайно оно окажется к примеру 1390 :biggrin: )
или просто в каждую датаграмму UDP складывал какое-то определнное количество данных, предположим 60 - тогда если максимальный размер пакета данных у тебя 20 байт ты пролезешь в фактически любое MTU по пути без особых сложностей, а в среднем датаграмма у тебя будет 900-1000 байт - вполне приемлимо и по pps у тебя выйдет.

ЗЫ: pps это packet per second - сетевое оборудование кроме N гигабит (пропускаемых внутри свича к примеру) имеет и такую характеристику, и если ее заваливать то тоже хорошего будет мало :biggrin:
Mad_Dollar
Не-не-не!:улыб:
Поток туда и поток оттуда это совершенно разные вещи.
У железки есть два основных режима работы: настройка и работа.

Настройка - Туда идёт поток команд управления. Фактически, от гуя софтины. Немного. 10-30 пакетов в секунду. И оттуда столько же (протокол подразумевает подтвержение каждой отработанной команды). Есть единичный пик при финальной засылке параметров - порядка 100-150 пакетов единомоментно, но, мне кажется, от такого единичного всплеска сеть не ляжет.

Работа - Оттуда идут те самые 8 Mbit, а туда - ничего. Если схемотехники дадут мне ОЗУ-шку, возможно буду туда запрашивать потерянные пакеты, но это пока в теории. И вот оттуда как раз я шлю пакеты максимального размера. Как раз для минимизации их количества.

И... раз уж зашёл разговор об MTU... Мне-то пофиг, я могу из константы сделать переменную, могу динамически определять его для каждого пакета (это не нужно, но я могу!:улыб:), но тогда встаёт естественный вопрос: а как его определить? Так-то, если на уровне софта его определить, то в режиме настройки я смог бы сообщить его железке, а та бы уже в работе гнала пакеты не более указанного количества.
AnotherBoris
В устройствах подобного рода настройки сети, и не толко сети, всегда задаются через конфигуратор.
Там определяется как назначается IP адрес статически/динамически, маска подсети, шлюз, и т.д.
Почему не задавать размер MTU через тот же конфигуратор? По дефолту MTU принять 1500, а если вдруг чего наладчик выставит нужное значение.
Что касается протокола транспортного уровня то для подобных устройств приемлем только TCP.
Если это конечно не бытовая поделка, а серьезное устройство для промышленного применения.
DarkXimik
А вобще вы зря замарочились на MTU.
Не помню что бы MTU можно было явно задавать в каких нибудь плк/измерительных преобразователях/преобразователях и конверторах интерфейсов.
AnotherBoris
И... раз уж зашёл разговор об MTU... Мне-то пофиг, я могу из константы сделать переменную, могу динамически определять его для каждого пакета (это не нужно, но я могу!
не, не стоит :biggrin: я говорю о том что ты просто "впритык" на 1460 не завязывайся