Commit 7a0b9df6 authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by David S. Miller

sctp: move the flush of ctrl chunks into its own function

Named sctp_outq_flush_ctrl and, with that, keep the contexts contained.

One small fix embedded is the reset of one_packet at every iteration.
This allows bundling of some control chunks in case they were preceeded by
another control chunk that cannot be bundled.

Other than this, it has the same behavior.

Changes since v2:
- Fixed panic reported by kbuild test robot if building with
  only up to this patch applied, due to bad parameter to
  sctp_outq_select_transport and by not initializing packet after
  calling sctp_outq_flush_ctrl.
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0d634b0c
...@@ -875,45 +875,21 @@ static bool sctp_outq_select_transport(struct sctp_chunk *chunk, ...@@ -875,45 +875,21 @@ static bool sctp_outq_select_transport(struct sctp_chunk *chunk,
return changed; return changed;
} }
/* static void sctp_outq_flush_ctrl(struct sctp_outq *q,
* Try to flush an outqueue. struct sctp_transport **_transport,
* struct list_head *transport_list,
* Description: Send everything in q which we legally can, subject to gfp_t gfp)
* 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_transport *transport = *_transport;
struct sctp_association *asoc = q->asoc; struct sctp_association *asoc = q->asoc;
__u32 vtag = asoc->peer.i.init_tag; struct sctp_packet *packet = NULL;
struct sctp_transport *transport = NULL;
struct sctp_chunk *chunk, *tmp; struct sctp_chunk *chunk, *tmp;
enum sctp_xmit status; enum sctp_xmit status;
int error = 0; int one_packet, error;
int start_timer = 0;
int one_packet = 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.
* ...
*/
list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
one_packet = 0;
/* RFC 5061, 5.3 /* RFC 5061, 5.3
* F1) This means that until such time as the ASCONF * F1) This means that until such time as the ASCONF
* containing the add is acknowledged, the sender MUST * containing the add is acknowledged, the sender MUST
...@@ -929,9 +905,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) ...@@ -929,9 +905,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
/* Pick the right transport to use. Should always be true for /* Pick the right transport to use. Should always be true for
* the first chunk as we don't have a transport by then. * the first chunk as we don't have a transport by then.
*/ */
if (sctp_outq_select_transport(chunk, asoc, &transport, if (sctp_outq_select_transport(chunk, asoc, _transport,
&transport_list)) transport_list)) {
transport = *_transport;
packet = &transport->packet; packet = &transport->packet;
}
switch (chunk->chunk_hdr->type) { switch (chunk->chunk_hdr->type) {
/* /*
...@@ -954,6 +932,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) ...@@ -954,6 +932,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
if (sctp_test_T_bit(chunk)) if (sctp_test_T_bit(chunk))
packet->vtag = asoc->c.my_vtag; packet->vtag = asoc->c.my_vtag;
/* fallthru */ /* fallthru */
/* The following chunks are "response" chunks, i.e. /* The following chunks are "response" chunks, i.e.
* they are generated in response to something we * they are generated in response to something we
* received. If we are sending these, then we can * received. If we are sending these, then we can
...@@ -1006,6 +985,47 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) ...@@ -1006,6 +985,47 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
BUG(); BUG();
} }
} }
}
/*
* 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;
__u32 vtag = asoc->peer.i.init_tag;
struct sctp_transport *transport = NULL;
struct sctp_chunk *chunk;
enum sctp_xmit status;
int error = 0;
int start_timer = 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) if (q->asoc->src_out_of_asoc_ok)
goto sctp_flush_out; goto sctp_flush_out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment