static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
struct sctp_chunk *chunk)
{
- sctp_xmit_t retval = SCTP_XMIT_OK;
size_t datasize, rwnd, inflight, flight_size;
struct sctp_transport *transport = packet->transport;
struct sctp_association *asoc = transport->asoc;
datasize = sctp_data_size(chunk);
- if (datasize > rwnd) {
- if (inflight > 0) {
- /* We have (at least) one data chunk in flight,
- * so we can't fall back to rule 6.1 B).
- */
- retval = SCTP_XMIT_RWND_FULL;
- goto finish;
- }
- }
+ if (datasize > rwnd && inflight > 0)
+ /* We have (at least) one data chunk in flight,
+ * so we can't fall back to rule 6.1 B).
+ */
+ return SCTP_XMIT_RWND_FULL;
/* RFC 2960 6.1 Transmission of DATA Chunks
*
* When a Fast Retransmit is being performed the sender SHOULD
* ignore the value of cwnd and SHOULD NOT delay retransmission.
*/
- if (chunk->fast_retransmit != SCTP_NEED_FRTX)
- if (flight_size >= transport->cwnd) {
- retval = SCTP_XMIT_RWND_FULL;
- goto finish;
- }
+ if (chunk->fast_retransmit != SCTP_NEED_FRTX &&
+ flight_size >= transport->cwnd)
+ return SCTP_XMIT_RWND_FULL;
/* Nagle's algorithm to solve small-packet problem:
* Inhibit the sending of new chunks when new outgoing data arrives
* if any previously transmitted data on the connection remains
* unacknowledged.
*/
- if (!sctp_sk(asoc->base.sk)->nodelay && sctp_packet_empty(packet) &&
- inflight && sctp_state(asoc, ESTABLISHED)) {
- unsigned int max = transport->pathmtu - packet->overhead;
- unsigned int len = chunk->skb->len + q->out_qlen;
-
- /* Check whether this chunk and all the rest of pending
- * data will fit or delay in hopes of bundling a full
- * sized packet.
- * Don't delay large message writes that may have been
- * fragmeneted into small peices.
- */
- if ((len < max) && chunk->msg->can_delay) {
- retval = SCTP_XMIT_NAGLE_DELAY;
- goto finish;
- }
- }
-finish:
- return retval;
+ if (sctp_sk(asoc->base.sk)->nodelay)
+ /* Nagle disabled */
+ return SCTP_XMIT_OK;
+
+ if (!sctp_packet_empty(packet))
+ /* Append to packet */
+ return SCTP_XMIT_OK;
+
+ if (inflight == 0)
+ /* Nothing unacked */
+ return SCTP_XMIT_OK;
+
+ if (!sctp_state(asoc, ESTABLISHED))
+ return SCTP_XMIT_OK;
+
+ /* Check whether this chunk and all the rest of pending data will fit
+ * or delay in hopes of bundling a full sized packet.
+ */
+ if (chunk->skb->len + q->out_qlen >= transport->pathmtu - packet->overhead)
+ /* Enough data queued to fill a packet */
+ return SCTP_XMIT_OK;
+
+ /* Don't delay large message writes that may have been fragmented */
+ if (!chunk->msg->can_delay)
+ return SCTP_XMIT_OK;
+
+ /* Defer until all data acked or packet full */
+ return SCTP_XMIT_NAGLE_DELAY;
}
/* This private function does management things when adding DATA chunk */