Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Изя Рнет, Вы писали:
ИР>>Здравствуйте, Pavel Dvorkin, Вы писали:
ИР>>Не изобретайте велосипед. Возьмите tcpflow (http://www.circlemud.org/~jelson/software/tcpflow/). Если не можете использовать код напрямую (как я понял, Вам надо на жаве), то перепишите, — кода, отвечающего за корректную сборку tcp-потока, там кот наплакал. За время не беспокойтесь, если приемник успевает собрать поток, то и вы успеете.
PD>Спасибо, но как вот это понимать ?
PD>However, it currently does not understand IP fragments; flows containing IP fragments will not be recorded properly
В каком-то из сообщений в этом треде Вы упомянули, что используется PMTUD. Поэтому, эта проблема вас беспокоить не должна. Но если таки надо, то дополните — еще ~30 строчек кода.
PD>Ну а велосипед уже вроде ездит
Если я правильно понял устройство Вашего велосипеда, то он сферический и в вакууме, а в реальных условиях сломается на счет раз.
Здравствуйте, Изя Рнет, Вы писали:
ИР>В каком-то из сообщений в этом треде Вы упомянули, что используется PMTUD. Поэтому, эта проблема вас беспокоить не должна. Но если таки надо, то дополните — еще ~30 строчек кода.
Я таки дико извиняюсь, но к стыду своему должен сказать, что я не знаю, что такое PMTUD
Я посмотрел этот код. Простите, куда мне этот поток записывать ? Там его в файл добавляют, это просто замечательно, он расти может неограниченно и никаких проблем. А мне даже выделение памяти делать не хочется, потому как время очень ограничено. Тут кольцевой буфер нужен, следить за ним и т.п. А мне бы просто — из IP пакета в буфер прикладного уровня на свое место. Понимаю, нехорошо это. Но на другое — нет времени. А если при этом .01% потеряю, не беда.
PD>>Ну а велосипед уже вроде ездит
ИР>Если я правильно понял устройство Вашего велосипеда, то он сферический и в вакууме, а в реальных условиях сломается на счет раз.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Да, кстати. Имейте в виду что последний Ethernet-кадр может быть больше чем требуется, у Ethernet есть ограничение на минимальный размер кадра.
Так, что-то не понял. Ethernet-кадры до меня не доходят, доходят IP-пакеты. Что, последний пакет может иметь большую длину, чем ему положено исходя из размера данных ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Изя Рнет, Вы писали:
ИР>>В каком-то из сообщений в этом треде Вы упомянули, что используется PMTUD. Поэтому, эта проблема вас беспокоить не должна. Но если таки надо, то дополните — еще ~30 строчек кода.
PD>Я таки дико извиняюсь, но к стыду своему должен сказать, что я не знаю, что такое PMTUD
Path MTU discovery. RFC1191.
Цитата из первого письма в этом треде:
Вместо этого у них разные идентификаторы, бит продолжения везде нулевой, смещение тоже ,а вот бит "не фрагментировать" стоит везде в 1.
Собственно, это оно и есть. Т.е. IP фрагментов у вас не будет. Но повторяю, дополнить это совсем несложно.
PD>Я посмотрел этот код. Простите, куда мне этот поток записывать ? Там его в файл добавляют, это просто замечательно, он расти может неограниченно и никаких проблем.
Ну так следите за этим буфером. Как только собралось полное сообщение протокола, обрабатываете и выкидываете.
PD>А мне даже выделение памяти делать не хочется, потому как время очень ограничено. Тут кольцевой буфер нужен, следить за ним и т.п. А мне бы просто — из IP пакета в буфер прикладного уровня на свое место. Понимаю, нехорошо это. Но на другое — нет времени. А если при этом .01% потеряю, не беда.
First make it work, then make it fast.
Не верю. Если стек приемника успевает честно собрать поток, отдать приложению, приложение успевает выбрать из потока сообщения и их обработать, то и вы успеете сделать то же самое. Если только речь не идет о том, что приемников сотни, суммарный поток на них гигабиты, а сниффер, который за этим следит, один.
PD>>>Ну а велосипед уже вроде ездит
ИР>>Если я правильно понял устройство Вашего велосипеда, то он сферический и в вакууме, а в реальных условиях сломается на счет раз.
PD>Посмотрим. Это очень легко проверяется
Нет. Это как со всеми race conditions. Может везти до определенного момента, а потом all hell breaks loose. Рассинхронизируетесь с потоком и потеряете неопределенное количество сообщений после.
Здравствуйте, Pavel Dvorkin, Вы писали:
MC>>Да, кстати. Имейте в виду что последний Ethernet-кадр может быть больше чем требуется, у Ethernet есть ограничение на минимальный размер кадра.
PD>Так, что-то не понял. Ethernet-кадры до меня не доходят, доходят IP-пакеты. PD>Что, последний пакет может иметь большую длину, чем ему положено исходя из размера данных ?
Хмм... Насколько я помню PCAP, доходят именно Ethernet-кадры. Хотя я не использовал WinPCAP, может там по-другому.
Ну да ладно, если у вас IP-пакеты, то не обращайте внимания, сказанное было про Ethernet-кадры и только про них.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Хмм... Насколько я помню PCAP, доходят именно Ethernet-кадры. Хотя я не использовал WinPCAP, может там по-другому.
JPCAP, надстройка над WinPCAP. Передает пакеты как экземпляры классов IPPacket и TCPPacket.
Здравствуйте, Изя Рнет, Вы писали:
ИР>Цитата из первого письма в этом треде: ИР>
ИР>Вместо этого у них разные идентификаторы, бит продолжения везде нулевой, смещение тоже ,а вот бит "не фрагментировать" стоит везде в 1.
ИР>Собственно, это оно и есть. Т.е. IP фрагментов у вас не будет. Но повторяю, дополнить это совсем несложно.
Понял, спасибо.
PD>>Я посмотрел этот код. Простите, куда мне этот поток записывать ? Там его в файл добавляют, это просто замечательно, он расти может неограниченно и никаких проблем.
ИР>Ну так следите за этим буфером. Как только собралось полное сообщение протокола, обрабатываете и выкидываете.
Эх, если бы. См ниже.
ИР>First make it work, then make it fast.
It already works but must task is to do it as fast as possible, even not 100% guarateed
ИР>Не верю. Если стек приемника успевает честно собрать поток, отдать приложению, приложение успевает выбрать из потока сообщения и их обработать, то и вы успеете сделать то же самое. Если только речь не идет о том, что приемников сотни,
По крайней мере десятки. И серверов тоже.
>суммарный поток на них гигабиты
Не могу сказать, не знаю пока.
>, а сниффер, который за этим следит, один.
Один. Именно так.
ИР>Нет. Это как со всеми race conditions. Может везти до определенного момента, а потом all hell breaks loose. Рассинхронизируетесь с потоком и потеряете неопределенное количество сообщений после.
А почему, собственно? Ладно, пусть я во многом не прав. Но если забыть все, что я намерен делать и просто ловить IP пакеты, не думая о TCP — это корректно ? Фильтровать их (подчеркиваю, IP-пакеты) по ip, port и protocol — тоже вроже бы. Пока нет ошибки ?
1: Дальше перескочим прямо на user data. Ищу там пакет с заголовком. Он определяется 100% надежно по моей логике. Не заголовок — выкинуть. Заголовок — из него знаю размер сообщения, то есть сумму ожидаемых пакетов и их seq. Дальше ловлю следующие пакеты в надежде, что они не заголовки и по seq попадают в нужный интервал. Ну пусть не придут — выкинем это сообщение. Пусть придут дважды — обработаем. Если придет новый пакет с заголовком , а прежнее сообщение не собрано — goto 1.
Как тут можно рассинхронизироваться, если синхронизация производится постоянно ?
Здравствуйте, Michael Chelnokov, Вы писали:
MC>У Java есть JNI, превосходно интегрируется с native-кодом, придется всего лишь вынести наружу несколько высокоуровневых функций.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>>Я посмотрел этот код. Простите, куда мне этот поток записывать ? Там его в файл добавляют, это просто замечательно, он расти может неограниченно и никаких проблем.
ИР>>Ну так следите за этим буфером. Как только собралось полное сообщение протокола, обрабатываете и выкидываете.
PD>Эх, если бы. См ниже.
Не понял, чему из ниже написанного это противоречит.
ИР>>First make it work, then make it fast.
PD>It already works but must task is to do it as fast as possible, even not 100% guarateed
ИР>>Не верю. Если стек приемника успевает честно собрать поток, отдать приложению, приложение успевает выбрать из потока сообщения и их обработать, то и вы успеете сделать то же самое. Если только речь не идет о том, что приемников сотни,
PD>По крайней мере десятки. И серверов тоже.
>>суммарный поток на них гигабиты
PD>Не могу сказать, не знаю пока.
>>, а сниффер, который за этим следит, один.
PD>Один. Именно так.
Сначала напишите как следует, измерьте производительность, и только потом, если производительность будет недостаточной, придумывайте противолодочные ходы.
Пока никаких предпосылок к тому, чтобы производительности при честном подходе не хватило, Вы не назвали. Сотни не очень быстрых tcp-потоков — это не фокус. Впрочем, Вам виднее, это Вы можете спрогнозировать нагрузку, а я не могу.
ИР>>Нет. Это как со всеми race conditions. Может везти до определенного момента, а потом all hell breaks loose. Рассинхронизируетесь с потоком и потеряете неопределенное количество сообщений после.
PD>А почему, собственно? Ладно, пусть я во многом не прав. Но если забыть все, что я намерен делать и просто ловить IP пакеты, не думая о TCP — это корректно ? Фильтровать их (подчеркиваю, IP-пакеты) по ip, port и protocol — тоже вроже бы. Пока нет ошибки ?
PD>1: Дальше перескочим прямо на user data. Ищу там пакет с заголовком. Он определяется 100% надежно по моей логике.
100% надежно, если он в середине пакета? 100% надежно, если заголовок порубился надвое и приехал двумя разными пакетами? Возможности обознаться и принять кусочек payload'а за заголовок сообщения нет?
PD> Не заголовок — выкинуть. Заголовок — из него знаю размер сообщения, то есть сумму ожидаемых пакетов и их seq. Дальше ловлю следующие пакеты в надежде, что они не заголовки и по seq попадают в нужный интервал.
Что, если сообщения "склеились" и конец предыдущего приехал вместе с началом следующего?
PD> Ну пусть не придут — выкинем это сообщение.
Когда? По таймауту, по обнаружению следующего заголовка?
PD> Пусть придут дважды — обработаем. Если придет новый пакет с заголовком , а прежнее сообщение не собрано — goto 1.
Т.е. out-of-order приводит к потере данных?
PD>Как тут можно рассинхронизироваться, если синхронизация производится постоянно ?
Если вы все реализуете аккуратно, то получите ту же самую сборку потока, только сложнее. Зачем?
Здравствуйте, Изя Рнет, Вы писали:
ИР>Не понял, чему из ниже написанного это противоречит.
Количеству серверов и клиентов и необходимости на сниффере выполнять дополнительную работу еще к тому же.
ИР>>>Не верю. Если стек приемника успевает честно собрать поток, отдать приложению, приложение успевает выбрать из потока сообщения и их обработать, то и вы успеете сделать то же самое. Если только речь не идет о том, что приемников сотни,
Какого приемника, какой стек ? В сети десятки серверов и клиентов. Они-то друг с другом нормально общаются со всеми стеками . А сниффер один. И он должен ловить все проходящие сообщения от всех серверов ко всем клиентам , фильтровать их по app-specific logic (а на это тоже время нужно) и в БД писать, на что тоже время требуется.
ИР>Сначала напишите как следует, измерьте производительность, и только потом, если производительность будет недостаточной, придумывайте противолодочные ходы.
Невозможно. Все это будет испытываться на реально работающей системе, а их характеристики (сисетем много) различны и никакое вмешатльсво в их работу невозможно. Везде не протестируешь. Надо писать наиболее быстро. Потеря 0.01% неактуальна, но захлебываться не может.
ИР>Пока никаких предпосылок к тому, чтобы производительности при честном подходе не хватило, Вы не назвали. Сотни не очень быстрых tcp-потоков — это не фокус. Впрочем, Вам виднее, это Вы можете спрогнозировать нагрузку, а я не могу.
Я тоже не могу, увы.
ИР>>>Нет. Это как со всеми race conditions. Может везти до определенного момента, а потом all hell breaks loose. Рассинхронизируетесь с потоком и потеряете неопределенное количество сообщений после.
PD>>А почему, собственно? Ладно, пусть я во многом не прав. Но если забыть все, что я намерен делать и просто ловить IP пакеты, не думая о TCP — это корректно ? Фильтровать их (подчеркиваю, IP-пакеты) по ip, port и protocol — тоже вроже бы. Пока нет ошибки ?
PD>>1: Дальше перескочим прямо на user data. Ищу там пакет с заголовком. Он определяется 100% надежно по моей логике.
ИР>100% надежно, если он в середине пакета?
А вот это и есть то самое предположение, что не очень надежно. Но если это один раз случится — он не будет опознан, как header. И пропущен по этой причине. Ищем следующий header. Ну а если такое будет часто — да, это значит, что я не прав. На модельной системе не было ни разу.
>100% надежно, если заголовок порубился надвое и приехал двумя разными пакетами?
Это то же самое.
>Возможности обознаться и принять кусочек payload'а за заголовок сообщения нет?
А вот это нет. То есть не 100% нет, но почти как CRC. Там масса свяких проверок потом.
ИР>Что, если сообщения "склеились" и конец предыдущего приехал вместе с началом следующего?
Контроль длины не пройдет. В user-data длина есть.
PD>> Ну пусть не придут — выкинем это сообщение.
ИР>Когда? По таймауту, по обнаружению следующего заголовка?
По обнаружению следующего заголовка.
PD>> Пусть придут дважды — обработаем. Если придет новый пакет с заголовком , а прежнее сообщение не собрано — goto 1.
ИР>Т.е. out-of-order приводит к потере данных?
Если они в пределах от хидера до хидера — (дубликат или не тот порядок, но в пределах сообщения) — никакой потери. Если же они после второго хидера — выбросить, поезд ушел, мы уже другим сообщением занимаемся.
PD>>Как тут можно рассинхронизироваться, если синхронизация производится постоянно ?
ИР>Если вы все реализуете аккуратно, то получите ту же самую сборку потока, только сложнее. Зачем?
Экономия. Нет буфера, нет дополнительного копирования. Данные из IP-пакета копируются прямо в app-layer буфер. Был бы это C++ а не Java — я бы IP пакеты прямо в app-layer буфер брал, в Яве не могу, увы.
Здравствуйте, Pavel Dvorkin, Вы писали:
ИР>>100% надежно, если он в середине пакета?
PD>А вот это и есть то самое предположение, что не очень надежно. Но если это один раз случится — он не будет опознан, как header. И пропущен по этой причине. Ищем следующий header. Ну а если такое будет часто — да, это значит, что я не прав. На модельной системе не было ни разу.
Это потому что она модельная. А в реальности "склеиться" в буфере передатчика может неопределенное количество сообщений, сегментироваться произвольным образом и тогда вы будете терять их все, пока вам не повезет и вы не восстановите синхронизацию. Это будет происходить нечасто, но верхней границы для худшего случая по потерянным сообщениям у вас нет, поэтому гарантировать непревышение какого-то определенного loss rate вы не можете (вернее можете, верхняя граница потерь — 100%) . И это даже в отсутствие перегрузки снифера.
Допустимо это или нет, решать Вам.
[...]
ИР>>Если вы все реализуете аккуратно, то получите ту же самую сборку потока, только сложнее. Зачем?
PD>Экономия. Нет буфера, нет дополнительного копирования. Данные из IP-пакета копируются прямо в app-layer буфер. Был бы это C++ а не Java — я бы IP пакеты прямо в app-layer буфер брал, в Яве не могу, увы.
Это вы собираетесь экономить одно копирование из памяти в память на фоне записи в БД? Не знаю как Вам, а мне смешно.
Здравствуйте, Изя Рнет, Вы писали:
ИР>Допустимо это или нет, решать Вам.
Поживем — увидим.
ИР>[...]
ИР>>>Если вы все реализуете аккуратно, то получите ту же самую сборку потока, только сложнее. Зачем?
PD>>Экономия. Нет буфера, нет дополнительного копирования. Данные из IP-пакета копируются прямо в app-layer буфер. Был бы это C++ а не Java — я бы IP пакеты прямо в app-layer буфер брал, в Яве не могу, увы.
ИР>Это вы собираетесь экономить одно копирование из памяти в память на фоне записи в БД? Не знаю как Вам, а мне смешно.
А мне нет. Этим займется другой поток, на своем процессоре. Это вообще не к спеху. Сообщение получено и в очередь его, а потом когда-нибудь и в БД запишут.
А вот как мне сниффер сделать многопоточным — если знаете, подскажите.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Изя Рнет, Вы писали:
ИР>>Допустимо это или нет, решать Вам.
PD>Поживем — увидим.
(пожимая плечам) Ну как хотите, мое дело предупредить.
ИР>>[...]
ИР>>>>Если вы все реализуете аккуратно, то получите ту же самую сборку потока, только сложнее. Зачем?
PD>>>Экономия. Нет буфера, нет дополнительного копирования. Данные из IP-пакета копируются прямо в app-layer буфер. Был бы это C++ а не Java — я бы IP пакеты прямо в app-layer буфер брал, в Яве не могу, увы.
ИР>>Это вы собираетесь экономить одно копирование из памяти в память на фоне записи в БД? Не знаю как Вам, а мне смешно.
PD>А мне нет. Этим займется другой поток, на своем процессоре. Это вообще не к спеху. Сообщение получено и в очередь его, а потом когда-нибудь и в БД запишут.
Throughput вашей системы будет ограничен именно БД.
PD>А вот как мне сниффер сделать многопоточным — если знаете, подскажите.
Вот так и сделать. Сам по себе libpcap вполне thread safe за исключением pcap_compile. Что там с жавовской оберткой, я не знаю, выясните сами. Так что если у вас несколько интерфейсов на машине со сниффером, можете повесить по нитке на каждый.
Можете иметь одну нитку на получение пакетов, а потом демультиплексировать их по worker'ам — для этого у вас есть 5-tuple. Только, ради всего святого, не делайте по одной нитке на tcp flow.
Здравствуйте, Изя Рнет, Вы писали:
ИР>(пожимая плечам) Ну как хотите, мое дело предупредить.
ИР>Throughput вашей системы будет ограничен именно БД.
Почему ? Предполагаете, что в очереди будет слишком много сообщений и поток записи в БД не успеет ? Это несущественно. Дело в том. что после сборки сообщения оно должно пройти через app filter, который может отсеять 90% их и даже больше.
PD>>А вот как мне сниффер сделать многопоточным — если знаете, подскажите.
ИР>Вот так и сделать. Сам по себе libpcap вполне thread safe за исключением pcap_compile. Что там с жавовской оберткой, я не знаю, выясните сами. Так что если у вас несколько интерфейсов на машине со сниффером, можете повесить по нитке на каждый.
Интерфейс пока что один. Но, может, можно и несколько сделать. А вот что я не понял — как при этом брать трафик. Все рабочие машины в одной сети, тут ничего изменить нельзя. Предположим, влезу я туда со своим двухинтерфейсным сниффером и начну слушать сеть по 2 сокетам. И что ? Мне же придут одни и те же пакеты.
Вот разве что на разных интерфейсах разные фильтры по IP поставить. Это идея. Подумаю. Спасибо.
ИР>Можете иметь одну нитку на получение пакетов, а потом демультиплексировать их по worker'ам — для этого у вас есть 5-tuple.
Хм. по worker'ам — это по потокам? Вряд ли. Накладные расходы на потоки все перекроют. Да и нет у меня 10 процессоров, только 2, а надо и в БД все же писать. Тут и пропустить пакет недолго из-за переключения потоков в это время...
Здравствуйте, Pavel Dvorkin, Вы писали:
ИР>>Вот так и сделать. Сам по себе libpcap вполне thread safe за исключением pcap_compile. Что там с жавовской оберткой, я не знаю, выясните сами. Так что если у вас несколько интерфейсов на машине со сниффером, можете повесить по нитке на каждый.
PD>Интерфейс пока что один. Но, может, можно и несколько сделать. А вот что я не понял — как при этом брать трафик. Все рабочие машины в одной сети, тут ничего изменить нельзя. Предположим, влезу я туда со своим двухинтерфейсным сниффером и начну слушать сеть по 2 сокетам. И что ? Мне же придут одни и те же пакеты.
Не обязательно. Если трафик со свитчей забирается через port monitoring, то тут может возникнуть дополнительная гибкость. Зависит от топологии сети, задавайте вопросы сетевому админу заказчика.
PD>Вот разве что на разных интерфейсах разные фильтры по IP поставить. Это идея. Подумаю. Спасибо.
Можете и так.
ИР>>Можете иметь одну нитку на получение пакетов, а потом демультиплексировать их по worker'ам — для этого у вас есть 5-tuple.
PD>Хм. по worker'ам — это по потокам? Вряд ли. Накладные расходы на потоки все перекроют. Да и нет у меня 10 процессоров, только 2, а надо и в БД все же писать. Тут и пропустить пакет недолго из-за переключения потоков в это время...
Меряйте, меряйте, меряйте. Не стройте сомнительных догадок, а меряйте. Выясняйте, где будут bottleneck'и: CPU при разборе, копирование в памяти, переключение тредов, запись в БД, app level разбор и валидация, что-там-еще. Пакет вы вряд ли пропустите, есть буферы (не очень глубокие, впрочем) — хотя, Вы, вроде бы только что потерь не боялись . Только не заводите по worker-thread на каждый поток, создание/удаление ниток действительно сожрет все — это можно сказать заранее. Выгребание пакетов из интерфейса отдельной, выделенной нитью имеет то приемущество, что Вы можете сглаживать временные всплески активности при помощи длинных очередей к worker-thread'ам.
Здравствуйте, Изя Рнет, Вы писали:
ИР>Меряйте, меряйте, меряйте. Не стройте сомнительных догадок, а меряйте. Выясняйте, где будут bottleneck'и: CPU при разборе, копирование в памяти, переключение тредов, запись в БД, app level разбор и валидация, что-там-еще. Пакет вы вряд ли пропустите, есть буферы (не очень глубокие, впрочем) — хотя, Вы, вроде бы только что потерь не боялись .
Э, тут не все так просто. Я действительно не боюсь случайного пропуска пакета. Но если это превратится в систему, т.е начну терять, скажем, каждый сотый пакет, то все выйдет из строя.
>Только не заводите по worker-thread на каждый поток, создание/удаление ниток действительно сожрет все — это можно сказать заранее.
Потоки создавать я, конечно, на каждое сообщение и не собираюсь , это и ежу понятно . Один раз создается поток.
>Выгребание пакетов из интерфейса отдельной, выделенной нитью имеет то приемущество, что Вы можете сглаживать временные всплески активности при помощи длинных очередей к worker-thread'ам.
Вот это действительно мерять надо. Сама идея — по сути чистое заимствование идеи DPC , которая вроде бы неплохо работает, но там ядро, оно в этом месте непрерываемо. Здесь же , в третьем кольце, да еще на Яве с ее управлением потоками — тут действительно сказать сложно, надо мерять.
Спасибо за советы.
With best regards
Pavel Dvorkin
Re[2]: TCP пакеты
От:
Аноним
Дата:
24.01.08 13:44
Оценка:
PD>>а вот бит "не фрагментировать" стоит везде в 1. DOO>Скорее всего настройка — такие пакеты точно не дойдут до удаленного получателя (на просторах интернета слишком легко встретить участок с MTU < 1500 байт).
Вроде TCP старается не пользоваться услугами фрагментации поэтому сам занимается отслеживанием MTU — ему всё равно какими порциями слать, а IP уровню приятно — не надо фрагментировать. Именно для этого он поднимает Dont Fragment. А в крайнем случае, когда всё совсем фигово, он должен перейти на пакеты длиной 576 байт и убрать Dont Fragment.
Так что чтобы увидеть фрагментированный TCP пакет надо очень постараться.