sctp: do not update a_rwnd if we are not issuing a sack
[cascardo/linux.git] / net / sctp / sm_sideeffect.c
index b5327bb..7fe56d0 100644 (file)
@@ -215,10 +215,14 @@ 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 {
+               __u32 old_a_rwnd = asoc->a_rwnd;
+
                asoc->a_rwnd = asoc->rwnd;
                sack = sctp_make_sack(asoc);
-               if (!sack)
+               if (!sack) {
+                       asoc->a_rwnd = old_a_rwnd;
                        goto nomem;
+               }
 
                asoc->peer.sack_needed = 0;
                asoc->peer.sack_cnt = 0;
@@ -1019,13 +1023,13 @@ static void sctp_cmd_t1_timer_update(struct sctp_association *asoc,
  * encouraged for small fragments.
  */
 static int sctp_cmd_send_msg(struct sctp_association *asoc,
-                               struct sctp_datamsg *msg)
+                               struct sctp_datamsg *msg, gfp_t gfp)
 {
        struct sctp_chunk *chunk;
        int error = 0;
 
        list_for_each_entry(chunk, &msg->chunks, frag_list) {
-               error = sctp_outq_tail(&asoc->outqueue, chunk);
+               error = sctp_outq_tail(&asoc->outqueue, chunk, gfp);
                if (error)
                        break;
        }
@@ -1249,7 +1253,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_NEW_ASOC:
                        /* Register a new association.  */
                        if (local_cork) {
-                               sctp_outq_uncork(&asoc->outqueue);
+                               sctp_outq_uncork(&asoc->outqueue, gfp);
                                local_cork = 0;
                        }
 
@@ -1269,7 +1273,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 
                case SCTP_CMD_DELETE_TCB:
                        if (local_cork) {
-                               sctp_outq_uncork(&asoc->outqueue);
+                               sctp_outq_uncork(&asoc->outqueue, gfp);
                                local_cork = 0;
                        }
                        /* Delete the current association.  */
@@ -1423,13 +1427,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                local_cork = 1;
                        }
                        /* Send a chunk to our peer.  */
-                       error = sctp_outq_tail(&asoc->outqueue, cmd->obj.chunk);
+                       error = sctp_outq_tail(&asoc->outqueue, cmd->obj.chunk,
+                                              gfp);
                        break;
 
                case SCTP_CMD_SEND_PKT:
                        /* Send a full packet to our peer.  */
                        packet = cmd->obj.packet;
-                       sctp_packet_transmit(packet);
+                       sctp_packet_transmit(packet, gfp);
                        sctp_ootb_pkt_free(packet);
                        break;
 
@@ -1639,7 +1644,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                         */
                        chunk->pdiscard = 1;
                        if (asoc) {
-                               sctp_outq_uncork(&asoc->outqueue);
+                               sctp_outq_uncork(&asoc->outqueue, gfp);
                                local_cork = 0;
                        }
                        break;
@@ -1677,7 +1682,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_FORCE_PRIM_RETRAN:
                        t = asoc->peer.retran_path;
                        asoc->peer.retran_path = asoc->peer.primary_path;
-                       error = sctp_outq_uncork(&asoc->outqueue);
+                       error = sctp_outq_uncork(&asoc->outqueue, gfp);
                        local_cork = 0;
                        asoc->peer.retran_path = t;
                        break;
@@ -1704,7 +1709,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                sctp_outq_cork(&asoc->outqueue);
                                local_cork = 1;
                        }
-                       error = sctp_cmd_send_msg(asoc, cmd->obj.msg);
+                       error = sctp_cmd_send_msg(asoc, cmd->obj.msg, gfp);
                        break;
                case SCTP_CMD_SEND_NEXT_ASCONF:
                        sctp_cmd_send_asconf(asoc);
@@ -1734,9 +1739,9 @@ out:
         */
        if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) {
                if (chunk->end_of_packet || chunk->singleton)
-                       error = sctp_outq_uncork(&asoc->outqueue);
+                       error = sctp_outq_uncork(&asoc->outqueue, gfp);
        } else if (local_cork)
-               error = sctp_outq_uncork(&asoc->outqueue);
+               error = sctp_outq_uncork(&asoc->outqueue, gfp);
        return error;
 nomem:
        error = -ENOMEM;