Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LWIP прием длинных пакетов
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
viakon
LWIP фрагментированные пакеты собирает только если используется операционка? Использую standalone режим из примеров, при передаче пакета 2059 приходят два 1460 и 599. Как их правильно собрать в один? В инете пугают что они могут придти наборот вначале 599 байт.

STM32F107, LWIP 1.4.1, соединение TCP/IP.
doom13
Пробуйте посмотреть в направлении опции IP_REASSEMBLY. С приёмом не пробовал, но при отправке (IP_FRAG) фрагментация работала.
viakon
Цитата(doom13 @ Aug 10 2015, 11:50) *
Пробуйте посмотреть в направлении опции IP_REASSEMBLY.

Включено в opt.h.
doom13
Запускал пример от TI, там к проекту подтянут ещё lwipopts.h, где IP_REASSEEMBLY = 0. Может у Вас есть что-то похожее?
viakon
Цитата(doom13 @ Aug 10 2015, 14:27) *
Запускал пример от TI, там к проекту подтянут ещё lwipopts.h, где IP_REASSEEMBLY = 0. Может у Вас есть что-то похожее?

В lwipopts.h нет такого параметра.
alx2
Цитата(viakon @ Aug 10 2015, 10:07) *
при передаче пакета 2059 приходят два 1460 и 599.

соединение TCP/IP.

А разве в вашем пакете не установлен флаг "Don't fragment"?
Вообще-то при использовании TCP пакетам запрещают фрагментирование, и, если где-то в пути пакет превысил MTU, обратно отправляется icmp fragmentation needed...
scifi
Цитата(viakon @ Aug 10 2015, 07:07) *
... при передаче пакета 2059 приходят два 1460 и 599. Как их правильно собрать в один?
... соединение TCP/IP.

Уточните, что имеете в виду.
"Соединение TCP/IP" - имеется в виду соединение TCP? Если так, то при чём тут пакеты? Соединение TCP на высоком уровне - это поток байтов без разбивки на пакеты. В режиме raw API при отправке данных разбивка на пакеты происходит автоматически. При приёме автоматически упорядочиваются принятые пакеты и передаются на верхний уровень в виде цепочки буферов. Да, вам надо работать с этими буферами один за одним. Если у вас там есть кусок данных, размазанный по нескольким буферам, то вам придётся самому собирать его вместе (если это необходимо). Вы должны быть готовы к тому, что данные будут приходить в виде цепочки буферов размером 1 байт каждый.
kolobok0
Цитата(alx2 @ Aug 11 2015, 12:14) *
..при использовании TCP пакетам запрещают фрагментирование...


1) говоря о TCP не корректно говорить о пакетах. это ПОТОКОВЫЙ протокол..
2) Если Вы имеете ввиду IP пакеты, то выставление флага фрагментации не зависит от уровня более верхнего протокола.


Цитата(viakon @ Aug 10 2015, 07:07) *
LWIP фрагментированные пакеты...при передаче пакета 2059 приходят два 1460 и 599....они могут придти наборот вначале 599 байт....соединение TCP/IP.


у Вас полная каша.
1) как уже прозвучало выше TCP потоковый протокол, там ФИЗИЧЕСКИ НЕТ пакетов. Когда ведут разговор про TCP протокол, то подразумевают
именно то что декларировано RFC. Если ведёте речь о более низких протоколах стэка - то так и пишите IP, EthFrame
2) TCP ГАРАНТИРУЕТ последовательную передачу потока данных. Т.е. всевозможные "наоборот", для данного потока - враньё по определению.


при работе с данным протоколом Вы можете запихать на передатчике 1460+599 и получить 10+300+1740+9, а можете получить сразу 2059
одним присестом - в зависимости от многих условий... Но данные ГАРАНТИРОВАННО придут именно в той последовательности в которой
были переданы...
alx2
Цитата(kolobok0 @ Aug 11 2015, 20:50) *
1) говоря о TCP не корректно говорить о пакетах. это ПОТОКОВЫЙ протокол..

Хорошо. А через какой транспорт передается этот поток? У автора написано "TCP/IP". Говоря об IP корректно говорить о пакетах?

Цитата(kolobok0 @ Aug 11 2015, 20:50) *
2) Если Вы имеете ввиду IP пакеты, то выставление флага фрагментации не зависит от уровня более верхнего протокола.

То есть Вы считаете нормальным, когда IP пакет, несущий данные TCP, не имеет флага Don't fragment?
По-моему это ненормально, о чем я и написал viakon.
scifi
Цитата(alx2 @ Aug 12 2015, 07:46) *
Хорошо. А через какой транспорт передается этот поток? У автора написано "TCP/IP". Говоря об IP корректно говорить о пакетах?

Вы, наверное, не в курсе, что такое TCP/IP. Почитайте тут.
Это набор разных протоколов, многие из которых не имеют отношения к TCP, например ARP, ICMP, UDP.
Короче, TCP/IP - это слишком общий термин. Мы догадываемся, что автор имел в виду TCP, но вдруг ошибаемся?

Цитата(alx2 @ Aug 12 2015, 07:46) *
То есть Вы считаете нормальным, когда IP пакет, несущий данные TCP, не имеет флага Don't fragment?
По-моему это ненормально, о чем я и написал viakon.

Вот тут есть вполне чеканный ответ на этот вопрос.
Если в двух словах, то по-разному бывает.
alx2
Цитата(scifi @ Aug 12 2015, 11:21) *
Короче, TCP/IP - это слишком общий термин. Мы догадываемся, что автор имел в виду TCP, но вдруг ошибаемся?

Давайте не будем гадать, а попросим viakon уточнить, о каком именно пакете размером 2059 байт он говорил. Мне почему-то кажется, что это не ARP. sm.gif

Цитата(scifi @ Aug 12 2015, 11:21) *
Если в двух словах, то по-разному бывает.

Вопрос не в том, как бывает. Я допускаю, что TCP без DF возможно. Но вот нормально ли это? По вашей ссылке описана ситуация, когда сначала кто-то ломает в сети PMTUD, а потом в результате этого приходится убирать DF. Но когда сломано PMTUD - это уже ненормально...

Когда-то много лет назад в какой-то фидошной эхе спорили на эту тему (фрагментация IP пакетов). Я не поленился и поставил на одном из интернет-маршрутизаторов счетчики. Как оказалось, в реальной жизни ни одного (из многих миллионов) пакета (чтобы не было вопросов и догадок - я имею в виду пакета IP с кодом 6 в поле protocol) без флага DF не встретилось (за исключением TCP RST, которые большими не бывают). Это я к тому, как бывает в реальной жизни...

Поэтому, повторю, если у viakon пакет с данными передается без флага DF, ему, как минимум, надо обратить на это внимание и задуматься, почему так. Если, как в примере по ссылке, у него PMTUD сломано, так наверное лучше починить сломанное, чем бороться со следствиями...
scifi
Цитата(alx2 @ Aug 14 2015, 08:05) *
Давайте не будем гадать, а попросим viakon уточнить

Он, похоже, потерял интерес к этой теме laughing.gif
Это всё интересно, конечно, про фрагментацию IP пакетов. Но мне-то кажется, что он просто ожидал отправить по TCP пачку данных размером около 2 КБ и принять такую же пачку на другой стороне. А оказалось, что lwip разбил эту пачку на кусочки (потому что сильно сомневаюсь, что MSS больше 2 КБ). Я просто обратил его внимание, что в режиме raw API по-другому и не будет, вот и всё. И фрагментация на уровне IP здесь ни при чём.
Quasar
А вот вопрос, по практике. У меня на одной железке, начались проблемы со сборкой фрагментированных IP пакетов. В LwIP IP_REASSEEMBLY = 1, и иногда, при приеме например ICMP размером 30Кбайт, стеку не хватает памяти (malloc возвращает NULL), и обмен подвисает, пока стек не очистит очередь IP фрагментов, ожидающих сборки, я взял и отключил IP_REASSEEMBLY, теперь стек не задумывается, но вопрос, чем это не грозит?
viakon
Цитата(scifi @ Aug 14 2015, 11:54) *
Он, похоже, потерял интерес к этой теме laughing.gif
Это всё интересно, конечно, про фрагментацию IP пакетов. Но мне-то кажется, что он просто ожидал отправить по TCP пачку данных размером около 2 КБ и принять такую же пачку на другой стороне. А оказалось, что lwip разбил эту пачку на кусочки (потому что сильно сомневаюсь, что MSS больше 2 КБ). Я просто обратил его внимание, что в режиме raw API по-другому и не будет, вот и всё. И фрагментация на уровне IP здесь ни при чём.

Интерес не пропал, на данный момент я решил проблему уменьшением размера пакета до 1к, потому как времени на эксперименты уже не было.
Я думаю что все дело в том, что мне приходится пользоваться практически raw ip без участия операционки.
И тут прослеживается следующая логическая цепочка. На компе после содинения TCP послылаются в сокет данные 2059 байт, естественно они разбиваются на 2 пакета. Первый пакет длиной в 1460 полезных байт принимается мироконтроллером, вырабатывается прерывание и вызов LwIP_Pkt_Handle(), вызывает tcp_echoserver_recv (торопился, потому не стал даже переименовывать названия фнкций в примере), где я и получаю эти 1460 байт. Думаю что если подождать с обработкой LwIP_Pkt_Handle() то после прихода второго пакета я получу свои данные но все равно с разбивкой на 2 части в структуре pbuf.
FreeRTOS не хочу использовать мало ОЗУ. А ради эксперимента прикручивать FreeRTOS лениво.
scifi
Цитата(viakon @ Aug 17 2015, 09:32) *
Думаю что если подождать с обработкой LwIP_Pkt_Handle() то после прихода второго пакета я получу свои данные но все равно с разбивкой на 2 части в структуре pbuf.

Именно так оно и работает.
И ещё раз повторяю: нужно быть готовым к тому, что эти 2 килобайта придут в виде 2048 пакетов по 1 байту каждый. Экзотика, да, но вполне законно. В этом случае просто подождать не получится - память закончится. Поэтому нужно в отдельном буфере накапливать данные по мере их поступления, не откладывая. И освобождать ненужные буферы сразу.
viakon
Цитата(scifi @ Aug 17 2015, 12:42) *
Именно так оно и работает.
И ещё раз повторяю: нужно быть готовым к тому, что эти 2 килобайта придут в виде 2048 пакетов по 1 байту каждый. Экзотика, да, но вполне законно. В этом случае просто подождать не получится - память закончится. Поэтому нужно в отдельном буфере накапливать данные по мере их поступления, не откладывая. И освобождать ненужные буферы сразу.

Как понять что пакет уже весь дошел?
scifi
Цитата(viakon @ Aug 17 2015, 12:25) *
Как понять что пакет уже весь дошел?

Это уже должен протокол поверх TCP разбираться. Например, в HTTP есть заголовок Content-Length. Скажем, если написано "Content-Length: 2048", то браузер знает, что в ресурсе ровно 2048 байт. Когда все байты пришли - всё готово.
Так что вам виднее, как оно у вас должно работать.
dmitry-tomsk
Цитата(scifi @ Aug 17 2015, 12:35) *
Это уже должен протокол поверх TCP разбираться. Например, в HTTP есть заголовок Content-Length. Скажем, если написано "Content-Length: 2048", то браузер знает, что в ресурсе ровно 2048 байт. Когда все байты пришли - всё готово.
Так что вам виднее, как оно у вас должно работать.

Делал LwIp на xilinx, на пакеты разбивает по 1460 байт, пакеты там связаны, нужно использовать поле tot_len pbuf. Удобно пользовать pbuf_copy_partial.
kolobok0
Цитата(alx2 @ Aug 12 2015, 07:46) *
...Говоря об IP корректно говорить о пакетах? ...нормальным, когда IP пакет, ...не имеет флага Don't fragment?....


ниже TCP естественно используется IP (см. стэк). И естественно на уровне IP есть понятие пакетов, есть и сборка пакетов,
есть и флаг не дефрагментировать.
Но ТС говорит: пакеты при использование LWIP соединение TCP. Т.е. речь идёт именно об использовании а не реализации или как работать
с пакетами IP чтоб получить поток в TCP. Т.е. ТС явно мыслит на уровне использования стэка TCP.

по поводу флага. Он (и кстати другие флаги - например быстрой передачи или скажем признак спец флагов спецификация которых закрыта
для гражданского использования) вполне может стоять, а может и не стоять. Это не есть обязательное условие при использовании
какого-либо протокола, в том числе и TCP.

Цитата(viakon @ Aug 17 2015, 09:32) *
...прослеживается следующая логическая цепочка. На компе после содинения TCP послылаются в сокет данные 2059 байт, естественно они разбиваются на 2 пакета. Первый пакет..


попробуйте перевёрнутым кроссом соединить два девайса напрямую и повторите эксперимент.
Вы сильно удивитесь увидев другой результат sm.gif

Я Вам более скажу, что если будете посылать из под винды - будет один результат (без свитчей связь). Если будете посылать с девайса например -
будет другой результат(где отключите максимальную длину IP пакета, ну или измените её...) Вплоть до 65кил пакеты IP можно гнать - тут
нет никаких проблем...


Цитата(viakon @ Aug 17 2015, 12:25) *
Как понять что пакет уже весь дошел?


Если используете TCP уровень - там нет пакетов. Ну нет...физически...
В силу реализации софта, и ситуации в канале связи на данный момент времени - результат по группировки пересылаемых данных
не определён. TCP гарантирует последовательную доставку данных... Т.е. выпихнули - обязательно получите...
выпихнули 100+20+30+555+1
получите (в той же самой последовательности) 222+1+483

Как Вы там будете барахтаться в этом потоке принятых данных - Ваше право... Хоть по признаку начала заголовка данных,
хоть передачей в заголовка самой длины данных, хоть ..... как угодно...
Hold
Цитата(dmitry-tomsk @ Aug 18 2015, 20:16) *
Делал LwIp на xilinx, на пакеты разбивает по 1460 байт, пакеты там связаны, нужно использовать поле tot_len pbuf. Удобно пользовать pbuf_copy_partial.

Как именно стоит использовать поле tot_len?
У себя делал следующим образом:
1. Принимаю пакет netconn_recv(conn, &inbuf);
2. Определял длину пакета buflen = netbuf_len(inbuf);
3. Выделял память DataPtr = pvPortMalloc(buflen);
4. И копировал туда весь буфер netbuf_copy(inbuf,DataPtr,buflen);
Вопрос вот в чем: отправляю файл 200 кбайт, по логам вижу как прилетают пакеты:
Код
192.168.10.21:60293 data len:1460
192.168.10.21:60293 data len:20
192.168.10.21:60293 data len:1460
192.168.10.21:60293 data len:60
192.168.10.21:60293 data len:1460
192.168.10.21:60293 data len:20
192.168.10.21:60293 data len:1460
192.168.10.21:60293 data len:40
192.168.10.21:60293 data len:1460
192.168.10.21:60293 data len:20
192.168.10.21:60293 data len:760
192.168.10.21:60293 data len:45

Как понять что я все принял? Вводить таймаут, городить свой протокол поверх? Понимаю что это просто поток байт, но почему-то думал что возможно отследить что мы все получили
Сергей Борщ
QUOTE (Hold @ Jan 27 2017, 13:17) *
Как понять что я все принял? Вводить таймаут, городить свой протокол поверх?
Если работаете с TCP - то это потоковый протокол, передача длины или признак конца данных осуществляется в протоколе более верхнего уровня.
viakon
Цитата(Сергей Борщ @ Jan 27 2017, 16:29) *
Если работаете с TCP - то это потоковый протокол, передача длины или признак конца данных осуществляется в протоколе более верхнего уровня.


Т.е нужно писать свою обвязку к протоколу IP. Или не использовать длинные пакеты.
zltigo
Цитата(Сергей Борщ @ Jan 27 2017, 13:29) *
Если работаете с TCP - то это потоковый протокол

TCP ни разу потоковый протокол. Он пакетный.
Сергей Борщ
QUOTE (zltigo @ Jan 28 2017, 17:31) *
TCP ни разу потоковый протокол. Он пакетный.
Сокет открывается с параметром SOCK_STREAM. "Совпадение? Не думаю!".

И как тогда перевести этот отрывак из RFC:
QUOTE
Basic Data Transfer:

The TCP is able to transfer a continuous stream of octets in each
direction between its users by packaging some number of octets into
segments for transmission through the internet system. In general,
the TCPs decide when to block and forward data at their own
convenience.


zltigo
Цитата(Сергей Борщ @ Jan 28 2017, 20:20) *
И как тогда перевести этот отрывак из RFC:

Да как угодно. Что было голове написавшего STREAM, как признак того, что для передаваемых ПАКЕТОВ, не гарантируется их нефрагментироание, мне неведомо. Для пакетов с гарантированным отсутствием фрагментации бывает поддержка SEQPACKET режима сокета.
Протокол вне зависимости от режима сокета чисто пакетный - оформление фрейма, размер... Поверх TCP, да уже действительно потоковые протоколы в прямом понимании этого слова, навешиваются.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.