__u16 sport, __u16 dport);
 struct sctp_packet *sctp_packet_config(struct sctp_packet *, __u32 vtag, int);
 sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *,
-                                       struct sctp_chunk *);
+                                       struct sctp_chunk *, int);
 sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *,
                                      struct sctp_chunk *);
 int sctp_packet_transmit(struct sctp_packet *);
 
        struct sctp_chunk *chunk;
        struct sock *sk;
        struct sctp_inq *inqueue;
+       struct sctp_outq *outq;
        int state;
        sctp_subtype_t subtype;
        int error = 0;
 
  * packet can be sent only after receiving the COOKIE_ACK.
  */
 sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
-                                      struct sctp_chunk *chunk)
+                                      struct sctp_chunk *chunk,
+                                      int one_packet)
 {
        sctp_xmit_t retval;
        int error = 0;
                        /* If we have an empty packet, then we can NOT ever
                         * return PMTU_FULL.
                         */
-                       retval = sctp_packet_append_chunk(packet, chunk);
+                       if (!one_packet)
+                               retval = sctp_packet_append_chunk(packet,
+                                                                 chunk);
                }
                break;
 
 
        return error;
 }
 
+
 /*
  * Try to flush an outqueue.
  *
        sctp_xmit_t status;
        int error = 0;
        int start_timer = 0;
+       int one_packet = 0;
 
        /* These transports have chunks to send. */
        struct list_head transport_list;
                        if (sctp_test_T_bit(chunk)) {
                                packet->vtag = asoc->c.my_vtag;
                        }
-               case SCTP_CID_SACK:
-               case SCTP_CID_HEARTBEAT:
+               /* The following chunks are "response" chunks, i.e.
+                * they are generated in response to something we
+                * received.  If we are sending these, then we can
+                * send only 1 packet containing these chunks.
+                */
                case SCTP_CID_HEARTBEAT_ACK:
-               case SCTP_CID_SHUTDOWN:
                case SCTP_CID_SHUTDOWN_ACK:
-               case SCTP_CID_ERROR:
-               case SCTP_CID_COOKIE_ECHO:
                case SCTP_CID_COOKIE_ACK:
-               case SCTP_CID_ECN_ECNE:
+               case SCTP_CID_COOKIE_ECHO:
+               case SCTP_CID_ERROR:
                case SCTP_CID_ECN_CWR:
-               case SCTP_CID_ASCONF:
                case SCTP_CID_ASCONF_ACK:
+                       one_packet = 1;
+                       /* Fall throught */
+
+               case SCTP_CID_SACK:
+               case SCTP_CID_HEARTBEAT:
+               case SCTP_CID_SHUTDOWN:
+               case SCTP_CID_ECN_ECNE:
+               case SCTP_CID_ASCONF:
                case SCTP_CID_FWD_TSN:
-                       sctp_packet_transmit_chunk(packet, chunk);
+                       status = sctp_packet_transmit_chunk(packet, chunk,
+                                                           one_packet);
+                       if (status  != SCTP_XMIT_OK) {
+                               /* put the chunk back */
+                               list_add(&chunk->list, &q->control_chunk_list);
+                       }
                        break;
 
                default:
                                        atomic_read(&chunk->skb->users) : -1);
 
                        /* Add the chunk to the packet.  */
-                       status = sctp_packet_transmit_chunk(packet, chunk);
+                       status = sctp_packet_transmit_chunk(packet, chunk, 0);
 
                        switch (status) {
                        case SCTP_XMIT_PMTU_FULL:
         * Make sure the empty queue handler will get run later.
         */
        q->empty = (list_empty(&q->out_chunk_list) &&
-                   list_empty(&q->control_chunk_list) &&
                    list_empty(&q->retransmit));
        if (!q->empty)
                goto finish;
 
                                 struct sctp_association *asoc,
                                 struct sctp_sackhdr *sackh)
 {
-       int err;
+       int err = 0;
 
        if (sctp_outq_sack(&asoc->outqueue, sackh)) {
                /* There are no more TSNs awaiting SACK.  */
                                 SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN),
                                 asoc->state, asoc->ep, asoc, NULL,
                                 GFP_ATOMIC);
-       } else {
-               /* Windows may have opened, so we need
-                * to check if we have DATA to transmit
-                */
-               err = sctp_outq_flush(&asoc->outqueue, 0);
        }
 
        return err;
                        break;
 
                case SCTP_CMD_DISCARD_PACKET:
-                       /* We need to discard the whole packet.  */
+                       /* We need to discard the whole packet.
+                        * Uncork the queue since there might be
+                        * responses pending
+                        */
                        chunk->pdiscard = 1;
+                       if (asoc) {
+                               sctp_outq_uncork(&asoc->outqueue);
+                               local_cork = 0;
+                       }
                        break;
 
                case SCTP_CMD_RTO_PENDING:
        }
 
 out:
-       if (local_cork)
-               sctp_outq_uncork(&asoc->outqueue);
+       /* If this is in response to a received chunk, wait until
+        * we are done with the packet to open the queue so that we don't
+        * send multiple packets in response to a single request.
+        */
+       if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) {
+               if (chunk->end_of_packet || chunk->singleton)
+                       sctp_outq_uncork(&asoc->outqueue);
+       } else if (local_cork)
+                       sctp_outq_uncork(&asoc->outqueue);
        return error;
 nomem:
        error = -ENOMEM;
 
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
-
        /* This will send the COOKIE ACK */
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 
        if (asoc->autoclose)
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
        /* It may also notify its ULP about the successful
         * establishment of the association with a Communication Up
                goto nomem;
 
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
 
                }
        }
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
        repl = sctp_make_cookie_ack(new_asoc, chunk);
        if (!repl)
                goto nomem;
 
+       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+
        if (ev)
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                SCTP_ULPEVENT(ev));
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                        SCTP_ULPEVENT(ai_ev));
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
-
        return SCTP_DISPOSITION_CONSUME;
 
 nomem:
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                break;
        case SCTP_CID_ACTION_DISCARD_ERR:
-               /* Discard the packet.  */
-               sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
                /* Generate an ERROR chunk as response. */
                hdr = unk_chunk->chunk_hdr;
                err_chunk = sctp_make_op_error(asoc, unk_chunk,
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(err_chunk));
                }
+
+               /* Discard the packet.  */
+               sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                return SCTP_DISPOSITION_CONSUME;
                break;
        case SCTP_CID_ACTION_SKIP: