net: sctp: fix checksum marking for outgoing packets

Packets to devices without NETIF_F_SCTP_CSUM (including NETIF_F_NO_CSUM)
should be properly checksummed because the packets can be diverted or
rerouted after construction. This still leaves packets diverted from
NETIF_F_SCTP_CSUM-enabled devices with broken checksums. Fixing this
needs implementing software offload fallback in networking core.

For users of sctp_checksum_disable, skb->ip_summed should be left as
CHECKSUM_NONE and not CHECKSUM_UNNECESSARY as per include/linux/skbuff.h.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Michał Mirosław 2011-07-13 14:10:29 +00:00 committed by David S. Miller
parent 51414d4108
commit b73c43f884
1 changed files with 8 additions and 11 deletions

View File

@ -500,23 +500,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* Note: Adler-32 is no longer applicable, as has been replaced * Note: Adler-32 is no longer applicable, as has been replaced
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
*/ */
if (!sctp_checksum_disable && if (!sctp_checksum_disable) {
!(dst->dev->features & (NETIF_F_NO_CSUM | NETIF_F_SCTP_CSUM))) { if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) {
__u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
/* 3) Put the resultant value into the checksum field in the /* 3) Put the resultant value into the checksum field in the
* common header, and leave the rest of the bits unchanged. * common header, and leave the rest of the bits unchanged.
*/ */
sh->checksum = sctp_end_cksum(crc32); sh->checksum = sctp_end_cksum(crc32);
} else { } else {
if (dst->dev->features & NETIF_F_SCTP_CSUM) {
/* no need to seed pseudo checksum for SCTP */ /* no need to seed pseudo checksum for SCTP */
nskb->ip_summed = CHECKSUM_PARTIAL; nskb->ip_summed = CHECKSUM_PARTIAL;
nskb->csum_start = (skb_transport_header(nskb) - nskb->csum_start = (skb_transport_header(nskb) -
nskb->head); nskb->head);
nskb->csum_offset = offsetof(struct sctphdr, checksum); nskb->csum_offset = offsetof(struct sctphdr, checksum);
} else {
nskb->ip_summed = CHECKSUM_UNNECESSARY;
} }
} }