OSDN Git Service

sctp: move outq data rtx code out of sctp_outq_flush
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Mon, 14 May 2018 17:34:39 +0000 (14:34 -0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 May 2018 02:57:15 +0000 (22:57 -0400)
This patch renames current sctp_outq_flush_rtx to __sctp_outq_flush_rtx
and create a new sctp_outq_flush_rtx, with the code that was on
sctp_outq_flush. Again, the idea is to have functions with small and
defined objectives.

Yes, there is an open-coded path selection in the now sctp_outq_flush_rtx.
That is kept as is for now because it may be very different when we
implement retransmission path selection algorithms for CMT-SCTP.

Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/outqueue.c

index 92f14f5..49e80bf 100644 (file)
@@ -601,14 +601,14 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
 
 /*
  * Transmit DATA chunks on the retransmit queue.  Upon return from
- * sctp_outq_flush_rtx() the packet 'pkt' may contain chunks which
+ * __sctp_outq_flush_rtx() the packet 'pkt' may contain chunks which
  * need to be transmitted by the caller.
  * We assume that pkt->transport has already been set.
  *
  * The return value is a normal kernel error return value.
  */
-static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
-                              int rtx_timeout, int *start_timer)
+static int __sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
+                                int rtx_timeout, int *start_timer)
 {
        struct sctp_transport *transport = pkt->transport;
        struct sctp_chunk *chunk, *chunk1;
@@ -987,6 +987,57 @@ static void sctp_outq_flush_ctrl(struct sctp_outq *q,
        }
 }
 
+/* Returns false if new data shouldn't be sent */
+static bool sctp_outq_flush_rtx(struct sctp_outq *q,
+                               struct sctp_transport **_transport,
+                               struct list_head *transport_list,
+                               int rtx_timeout)
+{
+       struct sctp_transport *transport = *_transport;
+       struct sctp_packet *packet = transport ? &transport->packet : NULL;
+       struct sctp_association *asoc = q->asoc;
+       int error, start_timer = 0;
+
+       if (asoc->peer.retran_path->state == SCTP_UNCONFIRMED)
+               return false;
+
+       if (transport != asoc->peer.retran_path) {
+               /* Switch transports & prepare the packet.  */
+               transport = asoc->peer.retran_path;
+               *_transport = transport;
+
+               if (list_empty(&transport->send_ready))
+                       list_add_tail(&transport->send_ready,
+                                     transport_list);
+
+               packet = &transport->packet;
+               sctp_packet_config(packet, asoc->peer.i.init_tag,
+                                  asoc->peer.ecn_capable);
+       }
+
+       error = __sctp_outq_flush_rtx(q, packet, rtx_timeout, &start_timer);
+       if (error < 0)
+               asoc->base.sk->sk_err = -error;
+
+       if (start_timer) {
+               sctp_transport_reset_t3_rtx(transport);
+               transport->last_time_sent = jiffies;
+       }
+
+       /* This can happen on COOKIE-ECHO resend.  Only
+        * one chunk can get bundled with a COOKIE-ECHO.
+        */
+       if (packet->has_cookie_echo)
+               return false;
+
+       /* Don't send new data if there is still data
+        * waiting to retransmit.
+        */
+       if (!list_empty(&q->retransmit))
+               return false;
+
+       return true;
+}
 /*
  * Try to flush an outqueue.
  *
@@ -1000,12 +1051,10 @@ 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;
@@ -1053,45 +1102,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
                 * current cwnd).
                 */
                if (!list_empty(&q->retransmit)) {
-                       if (asoc->peer.retran_path->state == SCTP_UNCONFIRMED)
-                               goto sctp_flush_out;
-                       if (transport == asoc->peer.retran_path)
-                               goto retran;
-
-                       /* Switch transports & prepare the packet.  */
-
-                       transport = asoc->peer.retran_path;
-
-                       if (list_empty(&transport->send_ready)) {
-                               list_add_tail(&transport->send_ready,
-                                             &transport_list);
-                       }
-
+                       if (!sctp_outq_flush_rtx(q, &transport, &transport_list,
+                                                rtx_timeout))
+                               break;
+                       /* We may have switched current transport */
                        packet = &transport->packet;
-                       sctp_packet_config(packet, vtag,
-                                          asoc->peer.ecn_capable);
-               retran:
-                       error = sctp_outq_flush_rtx(q, packet,
-                                                   rtx_timeout, &start_timer);
-                       if (error < 0)
-                               asoc->base.sk->sk_err = -error;
-
-                       if (start_timer) {
-                               sctp_transport_reset_t3_rtx(transport);
-                               transport->last_time_sent = jiffies;
-                       }
-
-                       /* This can happen on COOKIE-ECHO resend.  Only
-                        * one chunk can get bundled with a COOKIE-ECHO.
-                        */
-                       if (packet->has_cookie_echo)
-                               goto sctp_flush_out;
-
-                       /* Don't send new data if there is still data
-                        * waiting to retransmit.
-                        */
-                       if (!list_empty(&q->retransmit))
-                               goto sctp_flush_out;
                }
 
                /* Apply Max.Burst limitation to the current transport in