Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb93cc5d authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by David S. Miller
Browse files

sctp: move flushing of data chunks out of sctp_outq_flush



To the new sctp_outq_flush_data. Again, smaller functions and with well
defined objectives.

Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 96e0418e
Loading
Loading
Loading
Loading
+75 −74
Original line number Diff line number Diff line
@@ -1038,46 +1038,17 @@ static bool sctp_outq_flush_rtx(struct sctp_outq *q,

	return true;
}
/*
 * Try to flush an outqueue.
 *
 * Description: Send everything in q which we legally can, subject to
 * congestion limitations.
 * * Note: This function can be called from multiple contexts so appropriate
 * locking concerns must be made.  Today we use the sock lock to protect
 * this function.
 */
static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)

static void sctp_outq_flush_data(struct sctp_outq *q,
				 struct sctp_transport **_transport,
				 struct list_head *transport_list,
				 int rtx_timeout, gfp_t gfp)
{
	struct sctp_packet *packet;
	struct sctp_transport *transport = *_transport;
	struct sctp_packet *packet = transport ? &transport->packet : NULL;
	struct sctp_association *asoc = q->asoc;
	struct sctp_transport *transport = NULL;
	struct sctp_chunk *chunk;
	enum sctp_xmit status;
	int error = 0;

	/* These transports have chunks to send. */
	struct list_head transport_list;
	struct list_head *ltransport;

	INIT_LIST_HEAD(&transport_list);
	packet = NULL;

	/*
	 * 6.10 Bundling
	 *   ...
	 *   When bundling control chunks with DATA chunks, an
	 *   endpoint MUST place control chunks first in the outbound
	 *   SCTP packet.  The transmitter MUST transmit DATA chunks
	 *   within a SCTP packet in increasing order of TSN.
	 *   ...
	 */

	sctp_outq_flush_ctrl(q, &transport, &transport_list, gfp);
	packet = &transport->packet;

	if (q->asoc->src_out_of_asoc_ok)
		goto sctp_flush_out;

	/* Is it OK to send data chunks?  */
	switch (asoc->state) {
@@ -1102,10 +1073,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
		 * current cwnd).
		 */
		if (!list_empty(&q->retransmit)) {
			if (!sctp_outq_flush_rtx(q, &transport, &transport_list,
			if (!sctp_outq_flush_rtx(q, _transport, transport_list,
						 rtx_timeout))
				break;
			/* We may have switched current transport */
			transport = *_transport;
			packet = &transport->packet;
		}

@@ -1131,12 +1103,14 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)

			if (asoc->stream.out[sid].state == SCTP_STREAM_CLOSED) {
				sctp_outq_head_data(q, chunk);
				goto sctp_flush_out;
				break;
			}

			if (sctp_outq_select_transport(chunk, asoc, &transport,
						       &transport_list))
			if (sctp_outq_select_transport(chunk, asoc, _transport,
						       transport_list)) {
				transport = *_transport;
				packet = &transport->packet;
			}

			pr_debug("%s: outq:%p, chunk:%p[%s], tx-tsn:0x%x skb->head:%p "
				 "skb->users:%d\n",
@@ -1148,8 +1122,10 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)

			/* Add the chunk to the packet.  */
			status = sctp_packet_transmit_chunk(packet, chunk, 0, gfp);

			switch (status) {
			case SCTP_XMIT_OK:
				break;

			case SCTP_XMIT_PMTU_FULL:
			case SCTP_XMIT_RWND_FULL:
			case SCTP_XMIT_DELAY:
@@ -1161,9 +1137,9 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
					 status);

				sctp_outq_head_data(q, chunk);
				goto sctp_flush_out;
				return;
			}

			case SCTP_XMIT_OK:
			/* The sender is in the SHUTDOWN-PENDING state,
			 * The sender MAY set the I-bit in the DATA
			 * chunk header.
@@ -1180,22 +1156,6 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
			 */
			sctp_sched_dequeue_done(q, chunk);

				break;

			default:
				BUG();
			}

			/* BUG: We assume that the sctp_packet_transmit()
			 * call below will succeed all the time and add the
			 * chunk to the transmitted list and restart the
			 * timers.
			 * It is possible that the call can fail under OOM
			 * conditions.
			 *
			 * Is this really a problem?  Won't this behave
			 * like a lost TSN?
			 */
			list_add_tail(&chunk->transmitted_list,
				      &transport->transmitted);

@@ -1206,7 +1166,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
			 * COOKIE-ECHO chunk.
			 */
			if (packet->has_cookie_echo)
				goto sctp_flush_out;
				break;
		}
		break;

@@ -1214,6 +1174,47 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
		/* Do nothing.  */
		break;
	}
}

/*
 * Try to flush an outqueue.
 *
 * Description: Send everything in q which we legally can, subject to
 * congestion limitations.
 * * Note: This function can be called from multiple contexts so appropriate
 * locking concerns must be made.  Today we use the sock lock to protect
 * this function.
 */
static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
{
	struct sctp_packet *packet;
	struct sctp_association *asoc = q->asoc;
	struct sctp_transport *transport = NULL;
	int error = 0;

	/* These transports have chunks to send. */
	struct list_head transport_list;
	struct list_head *ltransport;

	INIT_LIST_HEAD(&transport_list);
	packet = NULL;

	/*
	 * 6.10 Bundling
	 *   ...
	 *   When bundling control chunks with DATA chunks, an
	 *   endpoint MUST place control chunks first in the outbound
	 *   SCTP packet.  The transmitter MUST transmit DATA chunks
	 *   within a SCTP packet in increasing order of TSN.
	 *   ...
	 */

	sctp_outq_flush_ctrl(q, &transport, &transport_list, gfp);

	if (q->asoc->src_out_of_asoc_ok)
		goto sctp_flush_out;

	sctp_outq_flush_data(q, &transport, &transport_list, rtx_timeout, gfp);

sctp_flush_out: