linux/net/sctp
Alexander Sverdlin c08751c851 net: sctp: Fix data chunk fragmentation for MTU values which are not multiple of 4
net: sctp: Fix data chunk fragmentation for MTU values which are not multiple of 4

Initially the problem was observed with ipsec, but later it became clear that
SCTP data chunk fragmentation algorithm has problems with MTU values which are
not multiple of 4. Test program was used which just transmits 2000 bytes long
packets to other host. tcpdump was used to observe re-fragmentation in IP layer
after SCTP already fragmented data chunks.

With MTU 1500:
12:54:34.082904 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 1500)
    10.151.38.153.39303 > 10.151.24.91.54321: sctp (1) [DATA] (B) [TSN: 2366088589] [SID: 0] [SSEQ 1] [PPID 0x0]
12:54:34.082933 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 596)
    10.151.38.153.39303 > 10.151.24.91.54321: sctp (1) [DATA] (E) [TSN: 2366088590] [SID: 0] [SSEQ 1] [PPID 0x0]
12:54:34.090576 IP (tos 0x2,ECT(0), ttl 63, id 0, offset 0, flags [DF], proto SCTP (132), length 48)
    10.151.24.91.54321 > 10.151.38.153.39303: sctp (1) [SACK] [cum ack 2366088590] [a_rwnd 79920] [#gap acks 0] [#dup tsns 0]

With MTU 1499:
13:02:49.955220 IP (tos 0x2,ECT(0), ttl 64, id 48215, offset 0, flags [+], proto SCTP (132), length 1492)
    10.151.38.153.39084 > 10.151.24.91.54321: sctp[|sctp]
13:02:49.955249 IP (tos 0x2,ECT(0), ttl 64, id 48215, offset 1472, flags [none], proto SCTP (132), length 28)
    10.151.38.153 > 10.151.24.91: ip-proto-132
13:02:49.955262 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 600)
    10.151.38.153.39084 > 10.151.24.91.54321: sctp (1) [DATA] (E) [TSN: 404355346] [SID: 0] [SSEQ 1] [PPID 0x0]
13:02:49.956770 IP (tos 0x2,ECT(0), ttl 63, id 0, offset 0, flags [DF], proto SCTP (132), length 48)
    10.151.24.91.54321 > 10.151.38.153.39084: sctp (1) [SACK] [cum ack 404355346] [a_rwnd 79920] [#gap acks 0] [#dup tsns 0]

Here problem in data portion limit calculation leads to re-fragmentation in IP,
which is sub-optimal. The problem is max_data initial value, which doesn't take
into account the fact, that data chunk must be padded to 4-bytes boundary.
It's enough to correct max_data, because all later adjustments are correctly
aligned to 4-bytes boundary.

After the fix is applied, everything is fragmented correctly for uneven MTUs:
15:16:27.083881 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 1496)
    10.151.38.153.53417 > 10.151.24.91.54321: sctp (1) [DATA] (B) [TSN: 3077098183] [SID: 0] [SSEQ 1] [PPID 0x0]
15:16:27.083907 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 600)
    10.151.38.153.53417 > 10.151.24.91.54321: sctp (1) [DATA] (E) [TSN: 3077098184] [SID: 0] [SSEQ 1] [PPID 0x0]
15:16:27.085640 IP (tos 0x2,ECT(0), ttl 63, id 0, offset 0, flags [DF], proto SCTP (132), length 48)
    10.151.24.91.54321 > 10.151.38.153.53417: sctp (1) [SACK] [cum ack 3077098184] [a_rwnd 79920] [#gap acks 0] [#dup tsns 0]

The bug was there for years already, but
 - is a performance issue, the packets are still transmitted
 - doesn't show up with default MTU 1500, but possibly with ipsec (MTU 1438)

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nsn.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-09-04 13:20:27 -04:00
..
Kconfig net: sctp: get rid of SCTP_DBG_TSNS entirely 2013-07-02 00:08:03 -07:00
Makefile sctp: implement sctp association probing module 2010-04-30 22:41:09 -04:00
associola.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2013-08-16 15:37:26 -07:00
auth.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
bind_addr.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
chunk.c net: sctp: Fix data chunk fragmentation for MTU values which are not multiple of 4 2013-09-04 13:20:27 -04:00
command.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
debug.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
endpointola.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
input.c Revert "net: sctp: convert sctp_checksum_disable module param into sctp sysctl" 2013-08-09 13:09:41 -07:00
inqueue.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
ipv6.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
objcnt.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
output.c Revert "net: sctp: convert sctp_checksum_disable module param into sctp sysctl" 2013-08-09 13:09:41 -07:00
outqueue.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
primitive.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
probe.c net: sctp: probe: allow more advanced ingress filtering by mark 2013-09-03 21:44:11 -04:00
proc.c net: proc_fs: trivial: print UIDs as unsigned int 2013-08-15 14:37:46 -07:00
protocol.c Revert "net: sctp: convert sctp_checksum_disable module param into sctp sysctl" 2013-08-09 13:09:41 -07:00
sm_make_chunk.c net: sctp: sctp_verify_init: clean up mandatory checks and add comment 2013-08-29 15:54:48 -04:00
sm_sideeffect.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
sm_statefuns.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
sm_statetable.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
socket.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
ssnmap.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
sysctl.c Revert "net: sctp: convert sctp_checksum_disable module param into sctp sysctl" 2013-08-09 13:09:41 -07:00
transport.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2013-08-16 15:37:26 -07:00
tsnmap.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
ulpevent.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00
ulpqueue.c net: sctp: trivial: update bug report in header comment 2013-08-09 11:33:02 -07:00