Изменение вычисления контрольной суммы TCP - разгрузка TCP отключена

Я управляю TCP-пакетами с помощью netfilter, поэтому мне приходится пересчитывать контрольные суммы TCP и IP, которые работают должным образом.

Wireshark сообщает, что контрольные суммы верны на выходе с сервера (что также соответствует тому, что, по мнению клиента, они должны быть), но когда они достигают клиента, контрольная сумма всегда заменяется на 0xAA6A.

В обработчике пост-маршрутизации я вычисляю контрольную сумму TCP следующим образом ... после манипулирования адресами / портами.

 tcp_header->check = 0;
 tcp_header->check = tcp_v4_check(tcp_len,
   ip_header->saddr,
   ip_header->daddr,
   csum_partial((char *)tcp_header, tcp_len, 0));

Контрольная сумма IP в порядке, используя

 ip_send_check(ip_header);

На сервере не включена разгрузка TCP для RX или TX, а также она даже не поддерживается, я получаю неподдерживаемую ошибку при попытке включить или отключить.

Offload parameters for eth0:
rx-checksumming: off
tx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: off
tx-vlan-offload: off
ntuple-filters: off
receive-hashing: off

Еще один связанный с этим момент, в котором я не уверен ... Я также управляю пакетами / портами в хуке предварительной маршрутизации на сервере, и они принимаются транспортным уровнем и определенно попадают в мое приложение, независимо от того, что мне кажется делать с контрольной суммой TCP, я предполагал, что они будут отброшены, если контрольная сумма TCP не будет обновлена ​​после изменения IP-адреса / и порта.

Есть ли очевидная причина такого поведения или я неправильно понимаю часть сетевого стека?

Обновление:

Установка ip_summed на CHECKSUM_NONE останавливает пересчет контрольной суммы, как только она покидает мой код. В чем я не уверен, так это в том, почему он пересчитывается на неправильное фиксированное значение? Если я не установил его, он будет установлен на CHECKSUM_PARTIAL.


person DarkRyuu    schedule 14.05.2013    source источник


Ответы (1)


Если значение на другой стороне всегда одно и то же, я вижу две основные возможности: 1) вы перезаписываете контрольную сумму позже, после этого кода 2) tcp_len неверен. Вам также следует проверить, установлен ли NETIF_F_V4_CSUM в функциях sockbuff dev->, потому что ядро делает что-то другое в этом случае

person Guillaume    schedule 14.05.2013
comment
Контрольная сумма, по крайней мере, не перезаписывается в моем коде, и tcp_len должен быть правильным, поскольку я фактически получаю правильную контрольную сумму, пока она не покинет крючок постмаршрутизации netfilter (также виден Wireshark). Я посмотрю на NETIF_F_V4_CSUM. Установка skb- ›ip_summed на CHECKSUM_NONE, похоже, работает, в идеале это временное исправление, так как разгрузка была бы полезной. Я предполагаю, что разгрузка использует IP-адреса из пакета для псевдо-заголовка TCP? - person DarkRyuu; 14.05.2013
comment
какое было значение до того, как вы установили для него CHECKSUM_NONE? Когда вы говорите, что это работает, что вы видите на проводе для контрольной суммы после установки NONE? (или вы видите 0) Разгрузка в linux vanilla не делает ничего, кроме контрольной суммы на стороне отправки, но в любом случае ваш патч должен работать, несмотря ни на что. - person Guillaume; 15.05.2013
comment
Когда я устанавливаю для ip_summed значение CHECKSUM_NONE, контрольная сумма TCP верна, когда она покидает мой крючок netfilter (как и раньше), а также верна, когда она попадает на клиент (чего не было раньше). Я дополню вопрос дополнительной информацией. - person DarkRyuu; 15.05.2013
comment
Я не могу попробовать себя, но я думаю, что, задав для ip_summed значение CHECKSUM_NONE, вы в основном просите код TCP повторить контрольную сумму. Вы пытались установить фиктивное значение в проверке и оставить ip_summed равным CHECKSUM_NONE? Если я прав, он должен работать так же хорошо. Вот почему я спрашивал вас, каково значение ip_summed до того, как ваш код изменит его. Я считаю, что частичная контрольная сумма, которую вы выполняете в своем коде, будет работать, только если это CHECKSUM_PARTIAL. - person Guillaume; 15.05.2013