include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / net / sctp / sm_sideeffect.c
index 86426aa..4c5bed9 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/ip.h>
+#include <linux/gfp.h>
 #include <net/sock.h>
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
@@ -217,8 +218,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
        } else {
-               if (asoc->a_rwnd > asoc->rwnd)
-                       asoc->a_rwnd = asoc->rwnd;
+               asoc->a_rwnd = asoc->rwnd;
                sack = sctp_make_sack(asoc);
                if (!sack)
                        goto nomem;
@@ -440,14 +440,26 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
        /* The check for association's overall error counter exceeding the
         * threshold is done in the state function.
         */
-       /* When probing UNCONFIRMED addresses, the association overall
-        * error count is NOT incremented
+       /* We are here due to a timer expiration.  If the timer was
+        * not a HEARTBEAT, then normal error tracking is done.
+        * If the timer was a heartbeat, we only increment error counts
+        * when we already have an outstanding HEARTBEAT that has not
+        * been acknowledged.
+        * Additionaly, some tranport states inhibit error increments.
         */
-       if (transport->state != SCTP_UNCONFIRMED)
+       if (!is_hb) {
                asoc->overall_error_count++;
+               if (transport->state != SCTP_INACTIVE)
+                       transport->error_count++;
+        } else if (transport->hb_sent) {
+               if (transport->state != SCTP_UNCONFIRMED)
+                       asoc->overall_error_count++;
+               if (transport->state != SCTP_INACTIVE)
+                       transport->error_count++;
+       }
 
        if (transport->state != SCTP_INACTIVE &&
-           (transport->error_count++ >= transport->pathmaxrxt)) {
+           (transport->error_count > transport->pathmaxrxt)) {
                SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
                                         " transport IP: port:%d failed.\n",
                                         asoc,
@@ -464,11 +476,10 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
         * used to provide an upper bound to this doubling operation.
         *
         * Special Case:  the first HB doesn't trigger exponential backoff.
-        * The first unacknowleged HB triggers it.  We do this with a flag
+        * The first unacknowledged HB triggers it.  We do this with a flag
         * that indicates that we have an outstanding HB.
         */
        if (!is_hb || transport->hb_sent) {
-               transport->last_rto = transport->rto;
                transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
        }
 }
@@ -707,7 +718,7 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
 
        if (sctp_style(sk, TCP)) {
                /* Change the sk->sk_state of a TCP-style socket that has
-                * sucessfully completed a connect() call.
+                * successfully completed a connect() call.
                 */
                if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
                        sk->sk_state = SCTP_SS_ESTABLISHED;
@@ -931,6 +942,27 @@ static void sctp_cmd_t1_timer_update(struct sctp_association *asoc,
 
 }
 
+/* Send the whole message, chunk by chunk, to the outqueue.
+ * This way the whole message is queued up and bundling if
+ * encouraged for small fragments.
+ */
+static int sctp_cmd_send_msg(struct sctp_association *asoc,
+                               struct sctp_datamsg *msg)
+{
+       struct sctp_chunk *chunk;
+       int error = 0;
+
+       list_for_each_entry(chunk, &msg->chunks, frag_list) {
+               error = sctp_outq_tail(&asoc->outqueue, chunk);
+               if (error)
+                       break;
+       }
+
+       return error;
+}
+
+
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -1385,6 +1417,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        asoc->init_last_sent_to = t;
                        chunk->transport = t;
                        t->init_sent_count++;
+                       /* Set the new transport as primary */
+                       sctp_assoc_set_primary(asoc, t);
                        break;
 
                case SCTP_CMD_INIT_RESTART:
@@ -1500,7 +1534,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_PROCESS_CTSN:
                        /* Dummy up a SACK for processing. */
                        sackh.cum_tsn_ack = cmd->obj.be32;
-                       sackh.a_rwnd = 0;
+                       sackh.a_rwnd = asoc->peer.rwnd +
+                                       asoc->outqueue.outstanding_bytes;
                        sackh.num_gap_ack_blocks = 0;
                        sackh.num_dup_tsns = 0;
                        sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,
@@ -1575,7 +1610,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_UPDATE_INITTAG:
                        asoc->peer.i.init_tag = cmd->obj.u32;
                        break;
-
+               case SCTP_CMD_SEND_MSG:
+                       if (!asoc->outqueue.cork) {
+                               sctp_outq_cork(&asoc->outqueue);
+                               local_cork = 1;
+                       }
+                       error = sctp_cmd_send_msg(asoc, cmd->obj.msg);
+                       break;
                default:
                        printk(KERN_WARNING "Impossible command: %u, %p\n",
                               cmd->verb, cmd->obj.ptr);
@@ -1593,9 +1634,9 @@ out:
         */
        if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) {
                if (chunk->end_of_packet || chunk->singleton)
-                       sctp_outq_uncork(&asoc->outqueue);
+                       error = sctp_outq_uncork(&asoc->outqueue);
        } else if (local_cork)
-                       sctp_outq_uncork(&asoc->outqueue);
+               error = sctp_outq_uncork(&asoc->outqueue);
        return error;
 nomem:
        error = -ENOMEM;