sctp: Mark the tsn as received after all allocations finish
authorVlad Yasevich <vladislav.yasevich@hp.com>
Tue, 8 Jul 2008 09:28:39 +0000 (02:28 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 8 Jul 2008 09:28:39 +0000 (02:28 -0700)
If we don't have the buffer space or memory allocations fail,
the data chunk is dropped, but TSN is still reported as received.
This introduced a data loss that can't be recovered.  We should
only mark TSNs are received after memory allocations finish.
The one exception is the invalid stream identifier, but that's
due to user error and is reported back to the user.

This was noticed by Michael Tuexen.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/sm_statefuns.c
net/sctp/ulpevent.c

index 0c9d5a6950fe0c5842076fba62f54b58b497f105..fcdb45d1071bb9c0ca90c7b680145b5521c87f1d 100644 (file)
@@ -5899,12 +5899,6 @@ static int sctp_eat_data(const struct sctp_association *asoc,
                return SCTP_IERROR_NO_DATA;
        }
 
-       /* If definately accepting the DATA chunk, record its TSN, otherwise
-        * wait for renege processing.
-        */
-       if (SCTP_CMD_CHUNK_ULP == deliver)
-               sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
        chunk->data_accepted = 1;
 
        /* Note: Some chunks may get overcounted (if we drop) or overcounted
@@ -5924,6 +5918,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
         * and discard the DATA chunk.
         */
        if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
+               /* Mark tsn as received even though we drop it */
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
+
                err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
                                         &data_hdr->stream,
                                         sizeof(data_hdr->stream));
index ce6cda6b6994daaf5e1a64c09fdb31c126e07b5b..a1f654aea2687ea740a48596a927486869bb7f65 100644 (file)
@@ -710,6 +710,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        if (!skb)
                goto fail;
 
+       /* Now that all memory allocations for this chunk succeeded, we
+        * can mark it as received so the tsn_map is updated correctly.
+        */
+       sctp_tsnmap_mark(&asoc->peer.tsn_map, ntohl(chunk->subh.data_hdr->tsn));
+
        /* First calculate the padding, so we don't inadvertently
         * pass up the wrong length to the user.
         *