diff options
author | rrs <rrs@FreeBSD.org> | 2010-06-07 18:29:10 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2010-06-07 18:29:10 +0000 |
commit | 79f1540a6e376aeac8e821beeeed9ee73efe6068 (patch) | |
tree | c26e4903dcf57375a51425764f25a74d00b5a4c8 /sys/netinet | |
parent | de50224e92852178751a81d47695249fc681acd0 (diff) | |
download | FreeBSD-src-79f1540a6e376aeac8e821beeeed9ee73efe6068.zip FreeBSD-src-79f1540a6e376aeac8e821beeeed9ee73efe6068.tar.gz |
This fixes a BUG in the handling of the cum-ack calculation.
We were only paying attention to the nr-mapping-array. Which
seems to make sense on the surface, by definition things
up to the cum-ack should be deliverable thus in the nr-mapping-array.
However (there is always a gotcha) thats not true when it
comes to large messages. The stack may hold the message
while re-assembling it not not deliver it based on several
thresholds. If that happens (which it would for smaller
large messages) then the cum-ack is figured wrong. We
now properly use both arrays in the cum-ack calculation.
MFC after: 1 week.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/sctp_indata.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index e6713a3..83ab59f 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -2245,15 +2245,19 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb) /* * Now we also need to check the mapping array in a couple of ways. * 1) Did we move the cum-ack point? + * + * When you first glance at this you might think that all entries that + * make up the postion of the cum-ack would be in the nr-mapping + * array only.. i.e. things up to the cum-ack are always + * deliverable. Thats true with one exception, when its a fragmented + * message we may not deliver the data until some threshold (or all + * of it) is in place. So we must OR the nr_mapping_array and + * mapping_array to get a true picture of the cum-ack. */ struct sctp_association *asoc; int at; + uint8_t val; int slide_from, slide_end, lgap, distance; - - /* EY nr_mapping array variables */ - /* int nr_at; */ - /* int nr_last_all_ones = 0; */ - /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */ uint32_t old_cumack, old_base, old_highest, highest_tsn; asoc = &stcb->asoc; @@ -2268,11 +2272,12 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb) */ at = 0; for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { - if (asoc->nr_mapping_array[slide_from] == 0xff) { + val = asoc->nr_mapping_array[slide_from] | asoc->mapping_array[slide_from]; + if (val == 0xff) { at += 8; } else { /* there is a 0 bit */ - at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]]; + at += sctp_map_lookup_tab[val]; break; } } |