Перейти к содержанию
    

Пытаюсь на меге гонять данные через GPRS. Не стал я пользовать готовые стеки типа айпи и лвп. Пишу свое приложение - порезаный tcp на нет. Так вот вопрос к тем кто разбирался с этой тематикой. Как правильно посчитать контрольную сумму для TCP пакета? Смотрел я упомянутые стеки. там для IP и TCP пакета вроде одинаковый алгоритм. Я позаимствовал их код. Снифером смотрел сетевой трафик в локалке - для TCP такой вариант не проходит - не сходится контрольная сумма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пытаюсь на меге гонять данные через GPRS. Не стал я пользовать готовые стеки типа айпи и лвп. Пишу свое приложение - порезаный tcp на нет. Так вот вопрос к тем кто разбирался с этой тематикой. Как правильно посчитать контрольную сумму для TCP пакета? Смотрел я упомянутые стеки. там для IP и TCP пакета вроде одинаковый алгоритм. Я позаимствовал их код. Снифером смотрел сетевой трафик в локалке - для TCP такой вариант не проходит - не сходится контрольная сумма.

 

А ты не забыл, что в TCP есть еще псевдо-заголовок, который участвует в подсчете контрольной суммы, но не передается в канал связи?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не забыл. Я перед расчетом инициализирую чексум числом 6 + длина TCP и натравляю процедуру на начало IP адресов в буфере. Попробовал за основу взять расчет IP чексум, но менять порядок 16 битных данных. Стала сходиться. Можно было-бы забить. но где гарантия, что в другой среде не будет проблем. Еще посомтрел в микроайпи и лвайпи не меняется порядок. Да и статью почитал одну в которой сказано, что от изменения порядка 16 битных опрерандов контрольной суммы изменяется толькло порядок байтов результата.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Делаю так:

inline u16 checksum(u8* d, int l, u32 c)

{

while(l > 1)

{ c += *(u16*)d;

d += 2; l -= 2;

}

if(l) c += *d;

 

c = (c >> 16) + (c & 0xffff);

c += (c >> 16);

u16 ret = ((u16)(~c));

return ret;

}

 

где вызов:

 

u32 ph = (saddr) & 0xffff) + ( (saddr) >> 16) +

((daddr) & 0xffff) + ((daddr) >> 16) +

0x600 + ((u16)l);

 

u16 cs = checksum(d, l, ph);

u32 saddr и пр. берется из ип хедера.

Это для тсп.

 

для удп:

u32 ph = (saddr) & 0xffff) + ( (saddr) >> 16) +

((daddr) & 0xffff) + ((daddr) >> 16) +

0x1100 + ((u16)l);

 

u16 cs = checksum(d, l, ph);

 

для ип еще проще:

u16 cs = checksum(d, ihl, 0);

 

 

Не забываем, что для ип сумма считается только для заголовка.

Изменено пользователем ktod

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, попробую.

Увы не сходится. Я смотрел снифером пакет:

volatile unsigned char buf[] = {
0xC0, 0xA8, 0x01, 0x08,   //src addr
0xC0, 0xA8, 0x01, 0x0E,  //dst addr

0x11, 0x42, 0x13, 0x88,  //Сам TCP пакет всего 25 октетов
0x97, 0xD4, 0xA2, 0x11,
0x1B, 0x01, 0x1A, 0x63,
0x50, 0x18, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00,
0x31, 0x31, 0x31, 0x31, 0x31
};

Для него контрольная сумма 0x04EA. Может под нетбиосом как-то по другому считается?

 

Зато контрольная сумма сходится если посчитать этой процедуро предварительно tcp_crc = 6 + 25.

void Calc_TCP_CRC(unsigned char *buf, unsigned int len, unsigned int *tcp_crc)
{
  unsigned long crc = *tcp_crc;
  unsigned int *ptr_to_buf = (unsigned int*)buf;
  unsigned int i, tmp;

  i = 0;
  do
  {
    tmp = (*(ptr_to_buf))>>8;
    tmp += (*(ptr_to_buf++))<<8;
    crc += tmp;
    i += 2;
  }while(i<len);

  if((len/2) & 1) crc += *((unsigned char*)ptr_to_buf);

  crc = (crc >> 16) + crc & 0xffff;
  crc += (crc >> 16);
  crc=(unsigned int)(~crc);

  *tcp_crc = (unsigned int)crc;
}

volatile unsigned int tcp_crc = 6 + 25;

Calc_TCP_CRC((unsigned char *)&buf, 33, (unsigned int *)&tcp_crc);

 

По сути дела она работает как и ваша. Просто хотелось бы иметь одну процедуру. которая считала бы и для IP и для TCP как в вашем случае. в приаттаченой статье тоже говорится что одна функция. Не могу понять чего у меня не работает.

___________________________________TCPIP.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обратите внимание на 0x600 + ((u16)l) при расчете для тсп.

l - это длинна тсп пакета. т.е. длина используется два раза при расчете кс.

 

По сути дела строкой

volatile unsigned int tcp_crc = 6 + 25;

Вы это и делаете.

 

И если посмотреть на весь ip пакет будет понятно откуда взялось 0x600.

 

ЗЫ: Поищите другое описание тсп. Приведенное Вами, несколько сумбурное.

Изменено пользователем ktod

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Статья конечно не основание. Я почитываю соответствующий RFC. В статье просто некоторые ньюансы рассмотрены. В частности сказано, что как и вашем коде процедура расчета чексум общая для всех частей IP пакета. Но вот у меня не получается хоть тресни. Не могу понять почему у вас работает и в фриварных стеках. Наверное забью я на эту общую чексум и буду пользовать для каждо части свою процедуру. По крайней мере так сходится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Шепну по секрету, что очень уж долгая песня расчет CRC в 32-битном варианте - много загрузок, много регистров требуется... Поэтому лично я набрался наглости сделать так:

unsigned int rxcrc;

#pragma optimize=no_inline
void subrxcrc(unsigned int i)
{
i=rxcrc-i;
if (_CARRY) i--;
rxcrc=i;
}

 

Имеется в виду добавление одного слова к CRC.

 

На код стало куда более приятно смотреть...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Недурственная идея. А сам алгоритм у вас как вышерассмотренный? Используете тоже одну функцию для всех частей IP пакета?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Недурственная идея. А сам алгоритм у вас как вышерассмотренный? Используете тоже одну функцию для всех частей IP пакета?

 

Ох... Там через одно место для экономии... Так что прицепляю исходники моего TCP/IP стека через SLIP uNikeTCP.zip... Почитайте, может чего полезного извлечете... Есть там пара фишек типа переключения контекстов через setjmp/longjmp и т.д. Сделано под IAR.uNikeTCP.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Очень интересный код - вроде маленькой оси. Оказывается в яре есть функция смены порядка байтов __reverse. А я искал типа htons.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...