Merge branch 'master' into for-2.6.35
[safe/jmp/linux-2.6] / net / sctp / chunk.c
index 9292294..476caaf 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/net.h>
 #include <linux/inet.h>
 #include <linux/skbuff.h>
+#include <linux/slab.h>
 #include <net/sock.h>
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
@@ -57,6 +58,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg)
        msg->send_failed = 0;
        msg->send_error = 0;
        msg->can_abandon = 0;
+       msg->can_delay = 1;
        msg->expires_at = 0;
        INIT_LIST_HEAD(&msg->chunks);
 }
@@ -73,6 +75,19 @@ SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
        return msg;
 }
 
+void sctp_datamsg_free(struct sctp_datamsg *msg)
+{
+       struct sctp_chunk *chunk;
+
+       /* This doesn't have to be a _safe vairant because
+        * sctp_chunk_free() only drops the refs.
+        */
+       list_for_each_entry(chunk, &msg->chunks, frag_list)
+               sctp_chunk_free(chunk);
+
+       sctp_datamsg_put(msg);
+}
+
 /* Final destructruction of datamsg memory. */
 static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
 {
@@ -207,19 +222,31 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
        whole = 0;
        first_len = max;
 
+       /* Check to see if we have a pending SACK and try to let it be bundled
+        * with this message.  Do this if we don't have any data queued already.
+        * To check that, look at out_qlen and retransmit list.
+        * NOTE: we will not reduce to account for SACK, if the message would
+        * not have been fragmented.
+        */
+       if (timer_pending(&asoc->timers[SCTP_EVENT_TIMEOUT_SACK]) &&
+           asoc->outqueue.out_qlen == 0 &&
+           list_empty(&asoc->outqueue.retransmit) &&
+           msg_len > max)
+               max_data -= WORD_ROUND(sizeof(sctp_sack_chunk_t));
+
        /* Encourage Cookie-ECHO bundling. */
-       if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
+       if (asoc->state < SCTP_STATE_COOKIE_ECHOED)
                max_data -= SCTP_ARBITRARY_COOKIE_ECHO_LEN;
 
-               /* This is the biggesr first_len we can have */
-               if (first_len > max_data)
-                       first_len = max_data;
-       }
+       /* Now that we adjusted completely, reset first_len */
+       if (first_len > max_data)
+               first_len = max_data;
 
        /* Account for a different sized first fragment */
        if (msg_len >= first_len) {
                msg_len -= first_len;
                whole = 1;
+               msg->can_delay = 0;
        }
 
        /* How many full sized?  How many bytes leftover? */
@@ -237,9 +264,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
                if (0 == i)
                        frag |= SCTP_DATA_FIRST_FRAG;
 
-               if ((i == (whole - 1)) && !over)
+               if ((i == (whole - 1)) && !over) {
                        frag |= SCTP_DATA_LAST_FRAG;
 
+                       /* The application requests to set the I-bit of the
+                        * last DATA chunk of a user message when providing
+                        * the user message to the SCTP implementation.
+                        */
+                       if ((sinfo->sinfo_flags & SCTP_EOF) ||
+                           (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
+                               frag |= SCTP_DATA_SACK_IMM;
+               }
+
                chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
 
                if (!chunk)
@@ -271,6 +307,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
                else
                        frag = SCTP_DATA_LAST_FRAG;
 
+               if ((sinfo->sinfo_flags & SCTP_EOF) ||
+                   (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
+                       frag |= SCTP_DATA_SACK_IMM;
+
                chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
 
                if (!chunk)